Fix x86-64 build without multiarch.
[glibc.git] / sysdeps / x86_64 / strcmp.S
blob1b48f04172c83610c499cdc45f065a57462943ec
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 # ifndef ENTRY2
78 #  define ENTRY2(name) ENTRY (name)
79 #  define END2(name) END (name)
80 # endif
82         ENTRY2 (__strcasecmp)
83         movq    __libc_tsd_LOCALE@gottpoff(%rip),%rax
84         movq    %fs:(%rax),%rdx
86         // XXX 5 byte should be before the function
87         /* 5-byte NOP.  */
88         .byte   0x0f,0x1f,0x44,0x00,0x00
89 END2 (__strcasecmp)
90 # ifndef NO_NOLOCALE_ALIAS
91 weak_alias (__strcasecmp, strcasecmp)
92 libc_hidden_def (__strcasecmp)
93 # endif
94         /* FALLTHROUGH to strcasecmp_l.  */
95 #endif
97 ENTRY (BP_SYM (STRCMP))
98 #ifdef NOT_IN_libc
99 /* Simple version since we can't use SSE registers in ld.so.  */
100 L(oop): movb    (%rdi), %al
101         cmpb    (%rsi), %al
102         jne     L(neq)
103         incq    %rdi
104         incq    %rsi
105         testb   %al, %al
106         jnz     L(oop)
108         xorl    %eax, %eax
109         ret
111 L(neq): movl    $1, %eax
112         movl    $-1, %ecx
113         cmovbl  %ecx, %eax
114         ret
115 END (BP_SYM (STRCMP))
116 #else   /* NOT_IN_libc */
117 # ifdef USE_AS_STRCASECMP_L
118         /* We have to fall back on the C implementation for locales
119            with encodings not matching ASCII for single bytes.  */
120 #  if LOCALE_T___LOCALES != 0 || LC_CTYPE != 0
121         movq    LOCALE_T___LOCALES+LC_CTYPE*8(%rdx), %rax
122 #  else
123         movq    (%rdx), %rax
124 #  endif
125         testl   $0, LOCALE_DATA_VALUES+_NL_CTYPE_NONASCII_CASE*SIZEOF_VALUES(%rax)
126         jne     __strcasecmp_l_nonascii
127 # endif
130  * This implementation uses SSE to compare up to 16 bytes at a time.
131  */
132 # ifdef USE_AS_STRNCMP
133         test    %rdx, %rdx
134         je      LABEL(strcmp_exitz)
135         cmp     $1, %rdx
136         je      LABEL(Byte0)
137         mov     %rdx, %r11
138 # endif
139         mov     %esi, %ecx
140         mov     %edi, %eax
141 /* Use 64bit AND here to avoid long NOP padding.  */
142         and     $0x3f, %rcx             /* rsi alignment in cache line */
143         and     $0x3f, %rax             /* rdi alignment in cache line */
144 # ifdef USE_AS_STRCASECMP_L
145         .section .rodata.cst16,"aM",@progbits,16
146         .align 16
147 .Lbelowupper:
148         .quad   0x4040404040404040
149         .quad   0x4040404040404040
150 .Ltopupper:
151         .quad   0x5b5b5b5b5b5b5b5b
152         .quad   0x5b5b5b5b5b5b5b5b
153 .Ltouppermask:
154         .quad   0x2020202020202020
155         .quad   0x2020202020202020
156         .previous
157         movdqa  .Lbelowupper(%rip), %xmm5
158 # define UCLOW_reg %xmm5
159         movdqa  .Ltopupper(%rip), %xmm6
160 # define UCHIGH_reg %xmm6
161         movdqa  .Ltouppermask(%rip), %xmm7
162 # define LCQWORD_reg %xmm7
163 # endif
164         cmp     $0x30, %ecx
165         ja      LABEL(crosscache)       /* rsi: 16-byte load will cross cache line */
166         cmp     $0x30, %eax
167         ja      LABEL(crosscache)       /* rdi: 16-byte load will cross cache line */
168         movlpd  (%rdi), %xmm1
169         movlpd  (%rsi), %xmm2
170         movhpd  8(%rdi), %xmm1
171         movhpd  8(%rsi), %xmm2
172 # ifdef USE_AS_STRCASECMP_L
173 #  define TOLOWER(reg1, reg2) \
174         movdqa  reg1, %xmm8;                                    \
175         movdqa  UCHIGH_reg, %xmm9;                              \
176         movdqa  reg2, %xmm10;                                   \
177         movdqa  UCHIGH_reg, %xmm11;                             \
178         pcmpgtb UCLOW_reg, %xmm8;                               \
179         pcmpgtb reg1, %xmm9;                                    \
180         pcmpgtb UCLOW_reg, %xmm10;                              \
181         pcmpgtb reg2, %xmm11;                                   \
182         pand    %xmm9, %xmm8;                                   \
183         pand    %xmm11, %xmm10;                                 \
184         pand    LCQWORD_reg, %xmm8;                             \
185         pand    LCQWORD_reg, %xmm10;                            \
186         por     %xmm8, reg1;                                    \
187         por     %xmm10, reg2
188         TOLOWER (%xmm1, %xmm2)
189 # else
190 #  define TOLOWER(reg1, reg2)
191 # endif
192         pxor    %xmm0, %xmm0            /* clear %xmm0 for null char checks */
193         pcmpeqb %xmm1, %xmm0            /* Any null chars? */
194         pcmpeqb %xmm2, %xmm1            /* compare first 16 bytes for equality */
195         psubb   %xmm0, %xmm1            /* packed sub of comparison results*/
196         pmovmskb %xmm1, %edx
197         sub     $0xffff, %edx           /* if first 16 bytes are same, edx == 0xffff */
198         jnz     LABEL(less16bytes)      /* If not, find different value or null char */
199 # ifdef USE_AS_STRNCMP
200         sub     $16, %r11
201         jbe     LABEL(strcmp_exitz)     /* finish comparision */
202 # endif
203         add     $16, %rsi               /* prepare to search next 16 bytes */
204         add     $16, %rdi               /* prepare to search next 16 bytes */
206         /*
207          * Determine source and destination string offsets from 16-byte alignment.
208          * Use relative offset difference between the two to determine which case
209          * below to use.
210          */
211         .p2align 4
212 LABEL(crosscache):
213         and     $0xfffffffffffffff0, %rsi       /* force %rsi is 16 byte aligned */
214         and     $0xfffffffffffffff0, %rdi       /* force %rdi is 16 byte aligned */
215         mov     $0xffff, %edx                   /* for equivalent offset */
216         xor     %r8d, %r8d
217         and     $0xf, %ecx                      /* offset of rsi */
218         and     $0xf, %eax                      /* offset of rdi */
219         cmp     %eax, %ecx
220         je      LABEL(ashr_0)                   /* rsi and rdi relative offset same */
221         ja      LABEL(bigger)
222         mov     %edx, %r8d                      /* r8d is offset flag for exit tail */
223         xchg    %ecx, %eax
224         xchg    %rsi, %rdi
225 LABEL(bigger):
226         lea     15(%rax), %r9
227         sub     %rcx, %r9
228         lea     LABEL(unaligned_table)(%rip), %r10
229         movslq  (%r10, %r9,4), %r9
230         lea     (%r10, %r9), %r10
231         jmp     *%r10                           /* jump to corresponding case */
234  * The following cases will be handled by ashr_0
235  *  rcx(offset of rsi)  rax(offset of rdi)  relative offset  corresponding case
236  *        n(0~15)            n(0~15)           15(15+ n-n)         ashr_0
237  */
238         .p2align 4
239 LABEL(ashr_0):
241         movdqa  (%rsi), %xmm1
242         pxor    %xmm0, %xmm0                    /* clear %xmm0 for null char check */
243         pcmpeqb %xmm1, %xmm0                    /* Any null chars? */
244 # ifndef USE_AS_STRCASECMP_L
245         pcmpeqb (%rdi), %xmm1                   /* compare 16 bytes for equality */
246 # else
247         movdqa  (%rdi), %xmm2
248         TOLOWER (%xmm1, %xmm2)
249         pcmpeqb %xmm2, %xmm1                    /* compare 16 bytes for equality */
250 # endif
251         psubb   %xmm0, %xmm1                    /* packed sub of comparison results*/
252         pmovmskb %xmm1, %r9d
253         shr     %cl, %edx                       /* adjust 0xffff for offset */
254         shr     %cl, %r9d                       /* adjust for 16-byte offset */
255         sub     %r9d, %edx
256         /*
257          * edx must be the same with r9d if in left byte (16-rcx) is equal to
258          * the start from (16-rax) and no null char was seen.
259          */
260         jne     LABEL(less32bytes)              /* mismatch or null char */
261         UPDATE_STRNCMP_COUNTER
262         mov     $16, %rcx
263         mov     $16, %r9
264         pxor    %xmm0, %xmm0                    /* clear xmm0, may have changed above */
266         /*
267          * Now both strings are aligned at 16-byte boundary. Loop over strings
268          * checking 32-bytes per iteration.
269          */
270         .p2align 4
271 LABEL(loop_ashr_0):
272         movdqa  (%rsi, %rcx), %xmm1
273         movdqa  (%rdi, %rcx), %xmm2
274         TOLOWER (%xmm1, %xmm2)
276         pcmpeqb %xmm1, %xmm0
277         pcmpeqb %xmm2, %xmm1
278         psubb   %xmm0, %xmm1
279         pmovmskb %xmm1, %edx
280         sub     $0xffff, %edx
281         jnz     LABEL(exit)             /* mismatch or null char seen */
283 # ifdef USE_AS_STRNCMP
284         sub     $16, %r11
285         jbe     LABEL(strcmp_exitz)
286 # endif
287         add     $16, %rcx
288         movdqa  (%rsi, %rcx), %xmm1
289         movdqa  (%rdi, %rcx), %xmm2
290         TOLOWER (%xmm1, %xmm2)
292         pcmpeqb %xmm1, %xmm0
293         pcmpeqb %xmm2, %xmm1
294         psubb   %xmm0, %xmm1
295         pmovmskb %xmm1, %edx
296         sub     $0xffff, %edx
297         jnz     LABEL(exit)
298 # ifdef USE_AS_STRNCMP
299         sub     $16, %r11
300         jbe     LABEL(strcmp_exitz)
301 # endif
302         add     $16, %rcx
303         jmp     LABEL(loop_ashr_0)
306  * The following cases will be handled by ashr_1
307  * rcx(offset of rsi)  rax(offset of rdi)   relative offset     corresponding case
308  *        n(15)            n -15            0(15 +(n-15) - n)         ashr_1
309  */
310         .p2align 4
311 LABEL(ashr_1):
312         pxor    %xmm0, %xmm0
313         movdqa  (%rdi), %xmm2
314         movdqa  (%rsi), %xmm1
315         pcmpeqb %xmm1, %xmm0            /* Any null chars? */
316         pslldq  $15, %xmm2              /* shift first string to align with second */
317         TOLOWER (%xmm1, %xmm2)
318         pcmpeqb %xmm1, %xmm2            /* compare 16 bytes for equality */
319         psubb   %xmm0, %xmm2            /* packed sub of comparison results*/
320         pmovmskb %xmm2, %r9d
321         shr     %cl, %edx               /* adjust 0xffff for offset */
322         shr     %cl, %r9d               /* adjust for 16-byte offset */
323         sub     %r9d, %edx
324         jnz     LABEL(less32bytes)      /* mismatch or null char seen */
325         movdqa  (%rdi), %xmm3
326         UPDATE_STRNCMP_COUNTER
328         pxor    %xmm0, %xmm0
329         mov     $16, %rcx               /* index for loads*/
330         mov     $1, %r9d                /* byte position left over from less32bytes case */
331         /*
332          * Setup %r10 value allows us to detect crossing a page boundary.
333          * When %r10 goes positive we have crossed a page boundary and
334          * need to do a nibble.
335          */
336         lea     1(%rdi), %r10
337         and     $0xfff, %r10            /* offset into 4K page */
338         sub     $0x1000, %r10           /* subtract 4K pagesize */
340         .p2align 4
341 LABEL(loop_ashr_1):
342         add     $16, %r10
343         jg      LABEL(nibble_ashr_1)    /* cross page boundary */
345 LABEL(gobble_ashr_1):
346         movdqa  (%rsi, %rcx), %xmm1
347         movdqa  (%rdi, %rcx), %xmm2
348         movdqa  %xmm2, %xmm4             /* store for next cycle */
350 # ifndef USE_SSSE3
351         psrldq  $1, %xmm3
352         pslldq  $15, %xmm2
353         por     %xmm3, %xmm2            /* merge into one 16byte value */
354 # else
355         palignr $1, %xmm3, %xmm2        /* merge into one 16byte value */
356 # endif
357         TOLOWER (%xmm1, %xmm2)
359         pcmpeqb %xmm1, %xmm0
360         pcmpeqb %xmm2, %xmm1
361         psubb   %xmm0, %xmm1
362         pmovmskb %xmm1, %edx
363         sub     $0xffff, %edx
364         jnz     LABEL(exit)
366 # ifdef USE_AS_STRNCMP
367         sub     $16, %r11
368         jbe     LABEL(strcmp_exitz)
369 # endif
370         add     $16, %rcx
371         movdqa  %xmm4, %xmm3
373         add     $16, %r10
374         jg      LABEL(nibble_ashr_1)    /* cross page boundary */
376         movdqa  (%rsi, %rcx), %xmm1
377         movdqa  (%rdi, %rcx), %xmm2
378         movdqa  %xmm2, %xmm4            /* store for next cycle */
380 # ifndef USE_SSSE3
381         psrldq  $1, %xmm3
382         pslldq  $15, %xmm2
383         por     %xmm3, %xmm2            /* merge into one 16byte value */
384 # else
385         palignr $1, %xmm3, %xmm2        /* merge into one 16byte value */
386 # endif
387         TOLOWER (%xmm1, %xmm2)
389         pcmpeqb %xmm1, %xmm0
390         pcmpeqb %xmm2, %xmm1
391         psubb   %xmm0, %xmm1
392         pmovmskb %xmm1, %edx
393         sub     $0xffff, %edx
394         jnz     LABEL(exit)
396 # ifdef USE_AS_STRNCMP
397         sub     $16, %r11
398         jbe     LABEL(strcmp_exitz)
399 # endif
400         add     $16, %rcx
401         movdqa  %xmm4, %xmm3
402         jmp     LABEL(loop_ashr_1)
404         /*
405          * Nibble avoids loads across page boundary. This is to avoid a potential
406          * access into unmapped memory.
407          */
408         .p2align 4
409 LABEL(nibble_ashr_1):
410         pcmpeqb %xmm3, %xmm0             /* check nibble for null char*/
411         pmovmskb %xmm0, %edx
412         test    $0xfffe, %edx
413         jnz     LABEL(ashr_1_exittail)  /* find null char*/
415 # ifdef USE_AS_STRNCMP
416         cmp     $14, %r11
417         jbe     LABEL(ashr_1_exittail)
418 # endif
420         pxor    %xmm0, %xmm0
421         sub     $0x1000, %r10           /* substract 4K from %r10 */
422         jmp     LABEL(gobble_ashr_1)
424         /*
425          * Once find null char, determine if there is a string mismatch
426          * before the null char.
427          */
428         .p2align 4
429 LABEL(ashr_1_exittail):
430         movdqa  (%rsi, %rcx), %xmm1
431         psrldq  $1, %xmm0
432         psrldq  $1, %xmm3
433         jmp     LABEL(aftertail)
436  * The following cases will be handled by ashr_2
437  * rcx(offset of rsi)  rax(offset of rdi)   relative offset   corresponding case
438  *        n(14~15)            n -14         1(15 +(n-14) - n)         ashr_2
439  */
440         .p2align 4
441 LABEL(ashr_2):
442         pxor    %xmm0, %xmm0
443         movdqa  (%rdi), %xmm2
444         movdqa  (%rsi), %xmm1
445         pcmpeqb %xmm1, %xmm0
446         pslldq  $14, %xmm2
447         TOLOWER (%xmm1, %xmm2)
448         pcmpeqb %xmm1, %xmm2
449         psubb   %xmm0, %xmm2
450         pmovmskb %xmm2, %r9d
451         shr     %cl, %edx
452         shr     %cl, %r9d
453         sub     %r9d, %edx
454         jnz     LABEL(less32bytes)
455         movdqa  (%rdi), %xmm3
456         UPDATE_STRNCMP_COUNTER
458         pxor    %xmm0, %xmm0
459         mov     $16, %rcx       /* index for loads */
460         mov     $2, %r9d        /* byte position left over from less32bytes case */
461         /*
462          * Setup %r10 value allows us to detect crossing a page boundary.
463          * When %r10 goes positive we have crossed a page boundary and
464          * need to do a nibble.
465          */
466         lea     2(%rdi), %r10
467         and     $0xfff, %r10    /* offset into 4K page */
468         sub     $0x1000, %r10   /* subtract 4K pagesize */
470         .p2align 4
471 LABEL(loop_ashr_2):
472         add     $16, %r10
473         jg      LABEL(nibble_ashr_2)
475 LABEL(gobble_ashr_2):
476         movdqa  (%rsi, %rcx), %xmm1
477         movdqa  (%rdi, %rcx), %xmm2
478         movdqa  %xmm2, %xmm4
480 # ifndef USE_SSSE3
481         psrldq  $2, %xmm3
482         pslldq  $14, %xmm2
483         por     %xmm3, %xmm2            /* merge into one 16byte value */
484 # else
485         palignr $2, %xmm3, %xmm2        /* merge into one 16byte value */
486 # endif
487         TOLOWER (%xmm1, %xmm2)
489         pcmpeqb %xmm1, %xmm0
490         pcmpeqb %xmm2, %xmm1
491         psubb   %xmm0, %xmm1
492         pmovmskb %xmm1, %edx
493         sub     $0xffff, %edx
494         jnz     LABEL(exit)
496 # ifdef USE_AS_STRNCMP
497         sub     $16, %r11
498         jbe     LABEL(strcmp_exitz)
499 # endif
501         add     $16, %rcx
502         movdqa  %xmm4, %xmm3
504         add     $16, %r10
505         jg      LABEL(nibble_ashr_2)    /* cross page boundary */
507         movdqa  (%rsi, %rcx), %xmm1
508         movdqa  (%rdi, %rcx), %xmm2
509         movdqa  %xmm2, %xmm4
511 # ifndef USE_SSSE3
512         psrldq  $2, %xmm3
513         pslldq  $14, %xmm2
514         por     %xmm3, %xmm2            /* merge into one 16byte value */
515 # else
516         palignr $2, %xmm3, %xmm2        /* merge into one 16byte value */
517 # endif
518         TOLOWER (%xmm1, %xmm2)
520         pcmpeqb %xmm1, %xmm0
521         pcmpeqb %xmm2, %xmm1
522         psubb   %xmm0, %xmm1
523         pmovmskb %xmm1, %edx
524         sub     $0xffff, %edx
525         jnz     LABEL(exit)
527 # ifdef USE_AS_STRNCMP
528         sub     $16, %r11
529         jbe     LABEL(strcmp_exitz)
530 # endif
532         add     $16, %rcx
533         movdqa  %xmm4, %xmm3
534         jmp     LABEL(loop_ashr_2)
536         .p2align 4
537 LABEL(nibble_ashr_2):
538         pcmpeqb %xmm3, %xmm0            /* check nibble for null char */
539         pmovmskb %xmm0, %edx
540         test    $0xfffc, %edx
541         jnz     LABEL(ashr_2_exittail)
543 # ifdef USE_AS_STRNCMP
544         cmp     $13, %r11
545         jbe     LABEL(ashr_2_exittail)
546 # endif
548         pxor    %xmm0, %xmm0
549         sub     $0x1000, %r10
550         jmp     LABEL(gobble_ashr_2)
552         .p2align 4
553 LABEL(ashr_2_exittail):
554         movdqa  (%rsi, %rcx), %xmm1
555         psrldq  $2, %xmm0
556         psrldq  $2, %xmm3
557         jmp     LABEL(aftertail)
560  * The following cases will be handled by ashr_3
561  *  rcx(offset of rsi)  rax(offset of rdi)  relative offset      corresponding case
562  *        n(13~15)            n -13         2(15 +(n-13) - n)         ashr_3
563  */
564         .p2align 4
565 LABEL(ashr_3):
566         pxor    %xmm0, %xmm0
567         movdqa  (%rdi), %xmm2
568         movdqa  (%rsi), %xmm1
569         pcmpeqb %xmm1, %xmm0
570         pslldq  $13, %xmm2
571         TOLOWER (%xmm1, %xmm2)
572         pcmpeqb %xmm1, %xmm2
573         psubb   %xmm0, %xmm2
574         pmovmskb %xmm2, %r9d
575         shr     %cl, %edx
576         shr     %cl, %r9d
577         sub     %r9d, %edx
578         jnz     LABEL(less32bytes)
579         movdqa  (%rdi), %xmm3
581         UPDATE_STRNCMP_COUNTER
583         pxor    %xmm0, %xmm0
584         mov     $16, %rcx       /* index for loads */
585         mov     $3, %r9d        /* byte position left over from less32bytes case */
586         /*
587          * Setup %r10 value allows us to detect crossing a page boundary.
588          * When %r10 goes positive we have crossed a page boundary and
589          * need to do a nibble.
590          */
591         lea     3(%rdi), %r10
592         and     $0xfff, %r10    /* offset into 4K page */
593         sub     $0x1000, %r10   /* subtract 4K pagesize */
595         .p2align 4
596 LABEL(loop_ashr_3):
597         add     $16, %r10
598         jg      LABEL(nibble_ashr_3)
600 LABEL(gobble_ashr_3):
601         movdqa  (%rsi, %rcx), %xmm1
602         movdqa  (%rdi, %rcx), %xmm2
603         movdqa  %xmm2, %xmm4
605 # ifndef USE_SSSE3
606         psrldq  $3, %xmm3
607         pslldq  $13, %xmm2
608         por     %xmm3, %xmm2            /* merge into one 16byte value */
609 # else
610         palignr $3, %xmm3, %xmm2        /* merge into one 16byte value */
611 # endif
612         TOLOWER (%xmm1, %xmm2)
614         pcmpeqb %xmm1, %xmm0
615         pcmpeqb %xmm2, %xmm1
616         psubb   %xmm0, %xmm1
617         pmovmskb %xmm1, %edx
618         sub     $0xffff, %edx
619         jnz     LABEL(exit)
621 # ifdef USE_AS_STRNCMP
622         sub     $16, %r11
623         jbe     LABEL(strcmp_exitz)
624 # endif
626         add     $16, %rcx
627         movdqa  %xmm4, %xmm3
629         add     $16, %r10
630         jg      LABEL(nibble_ashr_3)    /* cross page boundary */
632         movdqa  (%rsi, %rcx), %xmm1
633         movdqa  (%rdi, %rcx), %xmm2
634         movdqa  %xmm2, %xmm4
636 # ifndef USE_SSSE3
637         psrldq  $3, %xmm3
638         pslldq  $13, %xmm2
639         por     %xmm3, %xmm2            /* merge into one 16byte value */
640 # else
641         palignr $3, %xmm3, %xmm2        /* merge into one 16byte value */
642 # endif
643         TOLOWER (%xmm1, %xmm2)
645         pcmpeqb %xmm1, %xmm0
646         pcmpeqb %xmm2, %xmm1
647         psubb   %xmm0, %xmm1
648         pmovmskb %xmm1, %edx
649         sub     $0xffff, %edx
650         jnz     LABEL(exit)
652 # ifdef USE_AS_STRNCMP
653         sub     $16, %r11
654         jbe     LABEL(strcmp_exitz)
655 # endif
657         add     $16, %rcx
658         movdqa  %xmm4, %xmm3
659         jmp     LABEL(loop_ashr_3)
661         .p2align 4
662 LABEL(nibble_ashr_3):
663         pcmpeqb %xmm3, %xmm0            /* check nibble for null char */
664         pmovmskb %xmm0, %edx
665         test    $0xfff8, %edx
666         jnz     LABEL(ashr_3_exittail)
668 # ifdef USE_AS_STRNCMP
669         cmp     $12, %r11
670         jbe     LABEL(ashr_3_exittail)
671 # endif
673         pxor    %xmm0, %xmm0
674         sub     $0x1000, %r10
675         jmp     LABEL(gobble_ashr_3)
677         .p2align 4
678 LABEL(ashr_3_exittail):
679         movdqa  (%rsi, %rcx), %xmm1
680         psrldq  $3, %xmm0
681         psrldq  $3, %xmm3
682         jmp     LABEL(aftertail)
685  * The following cases will be handled by ashr_4
686  *  rcx(offset of rsi)  rax(offset of rdi)  relative offset      corresponding case
687  *        n(12~15)            n -12         3(15 +(n-12) - n)         ashr_4
688  */
689         .p2align 4
690 LABEL(ashr_4):
691         pxor    %xmm0, %xmm0
692         movdqa  (%rdi), %xmm2
693         movdqa  (%rsi), %xmm1
694         pcmpeqb %xmm1, %xmm0
695         pslldq  $12, %xmm2
696         TOLOWER (%xmm1, %xmm2)
697         pcmpeqb %xmm1, %xmm2
698         psubb   %xmm0, %xmm2
699         pmovmskb %xmm2, %r9d
700         shr     %cl, %edx
701         shr     %cl, %r9d
702         sub     %r9d, %edx
703         jnz     LABEL(less32bytes)
704         movdqa  (%rdi), %xmm3
706         UPDATE_STRNCMP_COUNTER
708         pxor    %xmm0, %xmm0
709         mov     $16, %rcx       /* index for loads */
710         mov     $4, %r9d        /* byte position left over from less32bytes case */
711         /*
712          * Setup %r10 value allows us to detect crossing a page boundary.
713          * When %r10 goes positive we have crossed a page boundary and
714          * need to do a nibble.
715          */
716         lea     4(%rdi), %r10
717         and     $0xfff, %r10    /* offset into 4K page */
718         sub     $0x1000, %r10   /* subtract 4K pagesize */
720         .p2align 4
721 LABEL(loop_ashr_4):
722         add     $16, %r10
723         jg      LABEL(nibble_ashr_4)
725 LABEL(gobble_ashr_4):
726         movdqa  (%rsi, %rcx), %xmm1
727         movdqa  (%rdi, %rcx), %xmm2
728         movdqa  %xmm2, %xmm4
730 # ifndef USE_SSSE3
731         psrldq  $4, %xmm3
732         pslldq  $12, %xmm2
733         por     %xmm3, %xmm2            /* merge into one 16byte value */
734 # else
735         palignr $4, %xmm3, %xmm2        /* merge into one 16byte value */
736 # endif
737         TOLOWER (%xmm1, %xmm2)
739         pcmpeqb %xmm1, %xmm0
740         pcmpeqb %xmm2, %xmm1
741         psubb   %xmm0, %xmm1
742         pmovmskb %xmm1, %edx
743         sub     $0xffff, %edx
744         jnz     LABEL(exit)
746 # ifdef USE_AS_STRNCMP
747         sub     $16, %r11
748         jbe     LABEL(strcmp_exitz)
749 # endif
751         add     $16, %rcx
752         movdqa  %xmm4, %xmm3
754         add     $16, %r10
755         jg      LABEL(nibble_ashr_4)    /* cross page boundary */
757         movdqa  (%rsi, %rcx), %xmm1
758         movdqa  (%rdi, %rcx), %xmm2
759         movdqa  %xmm2, %xmm4
761 # ifndef USE_SSSE3
762         psrldq  $4, %xmm3
763         pslldq  $12, %xmm2
764         por     %xmm3, %xmm2            /* merge into one 16byte value */
765 # else
766         palignr $4, %xmm3, %xmm2        /* merge into one 16byte value */
767 # endif
768         TOLOWER (%xmm1, %xmm2)
770         pcmpeqb %xmm1, %xmm0
771         pcmpeqb %xmm2, %xmm1
772         psubb   %xmm0, %xmm1
773         pmovmskb %xmm1, %edx
774         sub     $0xffff, %edx
775         jnz     LABEL(exit)
777 # ifdef USE_AS_STRNCMP
778         sub     $16, %r11
779         jbe     LABEL(strcmp_exitz)
780 # endif
782         add     $16, %rcx
783         movdqa  %xmm4, %xmm3
784         jmp     LABEL(loop_ashr_4)
786         .p2align 4
787 LABEL(nibble_ashr_4):
788         pcmpeqb %xmm3, %xmm0            /* check nibble for null char */
789         pmovmskb %xmm0, %edx
790         test    $0xfff0, %edx
791         jnz     LABEL(ashr_4_exittail)
793 # ifdef USE_AS_STRNCMP
794         cmp     $11, %r11
795         jbe     LABEL(ashr_4_exittail)
796 # endif
798         pxor    %xmm0, %xmm0
799         sub     $0x1000, %r10
800         jmp     LABEL(gobble_ashr_4)
802         .p2align 4
803 LABEL(ashr_4_exittail):
804         movdqa  (%rsi, %rcx), %xmm1
805         psrldq  $4, %xmm0
806         psrldq  $4, %xmm3
807         jmp     LABEL(aftertail)
810  * The following cases will be handled by ashr_5
811  *  rcx(offset of rsi)  rax(offset of rdi)        relative offset      corresponding case
812  *        n(11~15)          n - 11                4(15 +(n-11) - n)         ashr_5
813  */
814         .p2align 4
815 LABEL(ashr_5):
816         pxor    %xmm0, %xmm0
817         movdqa  (%rdi), %xmm2
818         movdqa  (%rsi), %xmm1
819         pcmpeqb %xmm1, %xmm0
820         pslldq  $11, %xmm2
821         TOLOWER (%xmm1, %xmm2)
822         pcmpeqb %xmm1, %xmm2
823         psubb   %xmm0, %xmm2
824         pmovmskb %xmm2, %r9d
825         shr     %cl, %edx
826         shr     %cl, %r9d
827         sub     %r9d, %edx
828         jnz     LABEL(less32bytes)
829         movdqa  (%rdi), %xmm3
831         UPDATE_STRNCMP_COUNTER
833         pxor    %xmm0, %xmm0
834         mov     $16, %rcx       /* index for loads */
835         mov     $5, %r9d        /* byte position left over from less32bytes case */
836         /*
837          * Setup %r10 value allows us to detect crossing a page boundary.
838          * When %r10 goes positive we have crossed a page boundary and
839          * need to do a nibble.
840          */
841         lea     5(%rdi), %r10
842         and     $0xfff, %r10    /* offset into 4K page */
843         sub     $0x1000, %r10   /* subtract 4K pagesize */
845         .p2align 4
846 LABEL(loop_ashr_5):
847         add     $16, %r10
848         jg      LABEL(nibble_ashr_5)
850 LABEL(gobble_ashr_5):
851         movdqa  (%rsi, %rcx), %xmm1
852         movdqa  (%rdi, %rcx), %xmm2
853         movdqa  %xmm2, %xmm4
855 # ifndef USE_SSSE3
856         psrldq  $5, %xmm3
857         pslldq  $11, %xmm2
858         por     %xmm3, %xmm2            /* merge into one 16byte value */
859 # else
860         palignr $5, %xmm3, %xmm2        /* merge into one 16byte value */
861 # endif
862         TOLOWER (%xmm1, %xmm2)
864         pcmpeqb %xmm1, %xmm0
865         pcmpeqb %xmm2, %xmm1
866         psubb   %xmm0, %xmm1
867         pmovmskb %xmm1, %edx
868         sub     $0xffff, %edx
869         jnz     LABEL(exit)
871 # ifdef USE_AS_STRNCMP
872         sub     $16, %r11
873         jbe     LABEL(strcmp_exitz)
874 # endif
876         add     $16, %rcx
877         movdqa  %xmm4, %xmm3
879         add     $16, %r10
880         jg      LABEL(nibble_ashr_5)    /* cross page boundary */
882         movdqa  (%rsi, %rcx), %xmm1
883         movdqa  (%rdi, %rcx), %xmm2
884         movdqa  %xmm2, %xmm4
886 # ifndef USE_SSSE3
887         psrldq  $5, %xmm3
888         pslldq  $11, %xmm2
889         por     %xmm3, %xmm2            /* merge into one 16byte value */
890 # else
891         palignr $5, %xmm3, %xmm2        /* merge into one 16byte value */
892 # endif
893         TOLOWER (%xmm1, %xmm2)
895         pcmpeqb %xmm1, %xmm0
896         pcmpeqb %xmm2, %xmm1
897         psubb   %xmm0, %xmm1
898         pmovmskb %xmm1, %edx
899         sub     $0xffff, %edx
900         jnz     LABEL(exit)
902 # ifdef USE_AS_STRNCMP
903         sub     $16, %r11
904         jbe     LABEL(strcmp_exitz)
905 # endif
907         add     $16, %rcx
908         movdqa  %xmm4, %xmm3
909         jmp     LABEL(loop_ashr_5)
911         .p2align 4
912 LABEL(nibble_ashr_5):
913         pcmpeqb %xmm3, %xmm0            /* check nibble for null char */
914         pmovmskb %xmm0, %edx
915         test    $0xffe0, %edx
916         jnz     LABEL(ashr_5_exittail)
918 # ifdef USE_AS_STRNCMP
919         cmp     $10, %r11
920         jbe     LABEL(ashr_5_exittail)
921 # endif
923         pxor    %xmm0, %xmm0
924         sub     $0x1000, %r10
925         jmp     LABEL(gobble_ashr_5)
927         .p2align 4
928 LABEL(ashr_5_exittail):
929         movdqa  (%rsi, %rcx), %xmm1
930         psrldq  $5, %xmm0
931         psrldq  $5, %xmm3
932         jmp     LABEL(aftertail)
935  * The following cases will be handled by ashr_6
936  *  rcx(offset of rsi)  rax(offset of rdi)        relative offset      corresponding case
937  *        n(10~15)          n - 10                5(15 +(n-10) - n)         ashr_6
938  */
939         .p2align 4
940 LABEL(ashr_6):
941         pxor    %xmm0, %xmm0
942         movdqa  (%rdi), %xmm2
943         movdqa  (%rsi), %xmm1
944         pcmpeqb %xmm1, %xmm0
945         pslldq  $10, %xmm2
946         TOLOWER (%xmm1, %xmm2)
947         pcmpeqb %xmm1, %xmm2
948         psubb   %xmm0, %xmm2
949         pmovmskb %xmm2, %r9d
950         shr     %cl, %edx
951         shr     %cl, %r9d
952         sub     %r9d, %edx
953         jnz     LABEL(less32bytes)
954         movdqa  (%rdi), %xmm3
956         UPDATE_STRNCMP_COUNTER
958         pxor    %xmm0, %xmm0
959         mov     $16, %rcx       /* index for loads */
960         mov     $6, %r9d        /* byte position left over from less32bytes case */
961         /*
962          * Setup %r10 value allows us to detect crossing a page boundary.
963          * When %r10 goes positive we have crossed a page boundary and
964          * need to do a nibble.
965          */
966         lea     6(%rdi), %r10
967         and     $0xfff, %r10    /* offset into 4K page */
968         sub     $0x1000, %r10   /* subtract 4K pagesize */
970         .p2align 4
971 LABEL(loop_ashr_6):
972         add     $16, %r10
973         jg      LABEL(nibble_ashr_6)
975 LABEL(gobble_ashr_6):
976         movdqa  (%rsi, %rcx), %xmm1
977         movdqa  (%rdi, %rcx), %xmm2
978         movdqa  %xmm2, %xmm4
980 # ifndef USE_SSSE3
981         psrldq  $6, %xmm3
982         pslldq  $10, %xmm2
983         por     %xmm3, %xmm2            /* merge into one 16byte value */
984 # else
985         palignr $6, %xmm3, %xmm2        /* merge into one 16byte value */
986 # endif
987         TOLOWER (%xmm1, %xmm2)
989         pcmpeqb %xmm1, %xmm0
990         pcmpeqb %xmm2, %xmm1
991         psubb   %xmm0, %xmm1
992         pmovmskb %xmm1, %edx
993         sub     $0xffff, %edx
994         jnz     LABEL(exit)
996 # ifdef USE_AS_STRNCMP
997         sub     $16, %r11
998         jbe     LABEL(strcmp_exitz)
999 # endif
1001         add     $16, %rcx
1002         movdqa  %xmm4, %xmm3
1004         add     $16, %r10
1005         jg      LABEL(nibble_ashr_6)    /* cross page boundary */
1007         movdqa  (%rsi, %rcx), %xmm1
1008         movdqa  (%rdi, %rcx), %xmm2
1009         movdqa  %xmm2, %xmm4
1011 # ifndef USE_SSSE3
1012         psrldq  $6, %xmm3
1013         pslldq  $10, %xmm2
1014         por     %xmm3, %xmm2            /* merge into one 16byte value */
1015 # else
1016         palignr $6, %xmm3, %xmm2        /* merge into one 16byte value */
1017 # endif
1018         TOLOWER (%xmm1, %xmm2)
1020         pcmpeqb %xmm1, %xmm0
1021         pcmpeqb %xmm2, %xmm1
1022         psubb   %xmm0, %xmm1
1023         pmovmskb %xmm1, %edx
1024         sub     $0xffff, %edx
1025         jnz     LABEL(exit)
1027 # ifdef USE_AS_STRNCMP
1028         sub     $16, %r11
1029         jbe     LABEL(strcmp_exitz)
1030 # endif
1032         add     $16, %rcx
1033         movdqa  %xmm4, %xmm3
1034         jmp     LABEL(loop_ashr_6)
1036         .p2align 4
1037 LABEL(nibble_ashr_6):
1038         pcmpeqb %xmm3, %xmm0            /* check nibble for null char */
1039         pmovmskb %xmm0, %edx
1040         test    $0xffc0, %edx
1041         jnz     LABEL(ashr_6_exittail)
1043 # ifdef USE_AS_STRNCMP
1044         cmp     $9, %r11
1045         jbe     LABEL(ashr_6_exittail)
1046 # endif
1048         pxor    %xmm0, %xmm0
1049         sub     $0x1000, %r10
1050         jmp     LABEL(gobble_ashr_6)
1052         .p2align 4
1053 LABEL(ashr_6_exittail):
1054         movdqa  (%rsi, %rcx), %xmm1
1055         psrldq  $6, %xmm0
1056         psrldq  $6, %xmm3
1057         jmp     LABEL(aftertail)
1060  * The following cases will be handled by ashr_7
1061  *  rcx(offset of rsi)  rax(offset of rdi)        relative offset      corresponding case
1062  *        n(9~15)          n - 9                6(15 +(n - 9) - n)         ashr_7
1063  */
1064         .p2align 4
1065 LABEL(ashr_7):
1066         pxor    %xmm0, %xmm0
1067         movdqa  (%rdi), %xmm2
1068         movdqa  (%rsi), %xmm1
1069         pcmpeqb %xmm1, %xmm0
1070         pslldq  $9, %xmm2
1071         TOLOWER (%xmm1, %xmm2)
1072         pcmpeqb %xmm1, %xmm2
1073         psubb   %xmm0, %xmm2
1074         pmovmskb %xmm2, %r9d
1075         shr     %cl, %edx
1076         shr     %cl, %r9d
1077         sub     %r9d, %edx
1078         jnz     LABEL(less32bytes)
1079         movdqa  (%rdi), %xmm3
1081         UPDATE_STRNCMP_COUNTER
1083         pxor    %xmm0, %xmm0
1084         mov     $16, %rcx       /* index for loads */
1085         mov     $7, %r9d        /* byte position left over from less32bytes case */
1086         /*
1087          * Setup %r10 value allows us to detect crossing a page boundary.
1088          * When %r10 goes positive we have crossed a page boundary and
1089          * need to do a nibble.
1090          */
1091         lea     7(%rdi), %r10
1092         and     $0xfff, %r10    /* offset into 4K page */
1093         sub     $0x1000, %r10   /* subtract 4K pagesize */
1095         .p2align 4
1096 LABEL(loop_ashr_7):
1097         add     $16, %r10
1098         jg      LABEL(nibble_ashr_7)
1100 LABEL(gobble_ashr_7):
1101         movdqa  (%rsi, %rcx), %xmm1
1102         movdqa  (%rdi, %rcx), %xmm2
1103         movdqa  %xmm2, %xmm4
1105 # ifndef USE_SSSE3
1106         psrldq  $7, %xmm3
1107         pslldq  $9, %xmm2
1108         por     %xmm3, %xmm2            /* merge into one 16byte value */
1109 # else
1110         palignr $7, %xmm3, %xmm2        /* merge into one 16byte value */
1111 # endif
1112         TOLOWER (%xmm1, %xmm2)
1114         pcmpeqb %xmm1, %xmm0
1115         pcmpeqb %xmm2, %xmm1
1116         psubb   %xmm0, %xmm1
1117         pmovmskb %xmm1, %edx
1118         sub     $0xffff, %edx
1119         jnz     LABEL(exit)
1121 # ifdef USE_AS_STRNCMP
1122         sub     $16, %r11
1123         jbe     LABEL(strcmp_exitz)
1124 # endif
1126         add     $16, %rcx
1127         movdqa  %xmm4, %xmm3
1129         add     $16, %r10
1130         jg      LABEL(nibble_ashr_7)    /* cross page boundary */
1132         movdqa  (%rsi, %rcx), %xmm1
1133         movdqa  (%rdi, %rcx), %xmm2
1134         movdqa  %xmm2, %xmm4
1136 # ifndef USE_SSSE3
1137         psrldq  $7, %xmm3
1138         pslldq  $9, %xmm2
1139         por     %xmm3, %xmm2            /* merge into one 16byte value */
1140 # else
1141         palignr $7, %xmm3, %xmm2        /* merge into one 16byte value */
1142 # endif
1143         TOLOWER (%xmm1, %xmm2)
1145         pcmpeqb %xmm1, %xmm0
1146         pcmpeqb %xmm2, %xmm1
1147         psubb   %xmm0, %xmm1
1148         pmovmskb %xmm1, %edx
1149         sub     $0xffff, %edx
1150         jnz     LABEL(exit)
1152 # ifdef USE_AS_STRNCMP
1153         sub     $16, %r11
1154         jbe     LABEL(strcmp_exitz)
1155 # endif
1157         add     $16, %rcx
1158         movdqa  %xmm4, %xmm3
1159         jmp     LABEL(loop_ashr_7)
1161         .p2align 4
1162 LABEL(nibble_ashr_7):
1163         pcmpeqb %xmm3, %xmm0            /* check nibble for null char */
1164         pmovmskb %xmm0, %edx
1165         test    $0xff80, %edx
1166         jnz     LABEL(ashr_7_exittail)
1168 # ifdef USE_AS_STRNCMP
1169         cmp     $8, %r11
1170         jbe     LABEL(ashr_7_exittail)
1171 # endif
1173         pxor    %xmm0, %xmm0
1174         sub     $0x1000, %r10
1175         jmp     LABEL(gobble_ashr_7)
1177         .p2align 4
1178 LABEL(ashr_7_exittail):
1179         movdqa  (%rsi, %rcx), %xmm1
1180         psrldq  $7, %xmm0
1181         psrldq  $7, %xmm3
1182         jmp     LABEL(aftertail)
1185  *  The following cases will be handled by ashr_8
1186  *  rcx(offset of rsi)  rax(offset of rdi)        relative offset        corresponding case
1187  *        n(8~15)          n - 8                7(15 +(n - 8) - n)         ashr_8
1188  */
1189         .p2align 4
1190 LABEL(ashr_8):
1191         pxor    %xmm0, %xmm0
1192         movdqa  (%rdi), %xmm2
1193         movdqa  (%rsi), %xmm1
1194         pcmpeqb %xmm1, %xmm0
1195         pslldq  $8, %xmm2
1196         TOLOWER (%xmm1, %xmm2)
1197         pcmpeqb %xmm1, %xmm2
1198         psubb   %xmm0, %xmm2
1199         pmovmskb %xmm2, %r9d
1200         shr     %cl, %edx
1201         shr     %cl, %r9d
1202         sub     %r9d, %edx
1203         jnz     LABEL(less32bytes)
1204         movdqa  (%rdi), %xmm3
1206         UPDATE_STRNCMP_COUNTER
1208         pxor    %xmm0, %xmm0
1209         mov     $16, %rcx       /* index for loads */
1210         mov     $8, %r9d        /* byte position left over from less32bytes case */
1211         /*
1212          * Setup %r10 value allows us to detect crossing a page boundary.
1213          * When %r10 goes positive we have crossed a page boundary and
1214          * need to do a nibble.
1215          */
1216         lea     8(%rdi), %r10
1217         and     $0xfff, %r10    /* offset into 4K page */
1218         sub     $0x1000, %r10   /* subtract 4K pagesize */
1220         .p2align 4
1221 LABEL(loop_ashr_8):
1222         add     $16, %r10
1223         jg      LABEL(nibble_ashr_8)
1225 LABEL(gobble_ashr_8):
1226         movdqa  (%rsi, %rcx), %xmm1
1227         movdqa  (%rdi, %rcx), %xmm2
1228         movdqa  %xmm2, %xmm4
1230 # ifndef USE_SSSE3
1231         psrldq  $8, %xmm3
1232         pslldq  $8, %xmm2
1233         por     %xmm3, %xmm2            /* merge into one 16byte value */
1234 # else
1235         palignr $8, %xmm3, %xmm2        /* merge into one 16byte value */
1236 # endif
1237         TOLOWER (%xmm1, %xmm2)
1239         pcmpeqb %xmm1, %xmm0
1240         pcmpeqb %xmm2, %xmm1
1241         psubb   %xmm0, %xmm1
1242         pmovmskb %xmm1, %edx
1243         sub     $0xffff, %edx
1244         jnz     LABEL(exit)
1246 # ifdef USE_AS_STRNCMP
1247         sub     $16, %r11
1248         jbe     LABEL(strcmp_exitz)
1249 # endif
1251         add     $16, %rcx
1252         movdqa  %xmm4, %xmm3
1254         add     $16, %r10
1255         jg      LABEL(nibble_ashr_8)    /* cross page boundary */
1257         movdqa  (%rsi, %rcx), %xmm1
1258         movdqa  (%rdi, %rcx), %xmm2
1259         movdqa  %xmm2, %xmm4
1261 # ifndef USE_SSSE3
1262         psrldq  $8, %xmm3
1263         pslldq  $8, %xmm2
1264         por     %xmm3, %xmm2            /* merge into one 16byte value */
1265 # else
1266         palignr $8, %xmm3, %xmm2        /* merge into one 16byte value */
1267 # endif
1268         TOLOWER (%xmm1, %xmm2)
1270         pcmpeqb %xmm1, %xmm0
1271         pcmpeqb %xmm2, %xmm1
1272         psubb   %xmm0, %xmm1
1273         pmovmskb %xmm1, %edx
1274         sub     $0xffff, %edx
1275         jnz     LABEL(exit)
1277 # ifdef USE_AS_STRNCMP
1278         sub     $16, %r11
1279         jbe     LABEL(strcmp_exitz)
1280 # endif
1282         add     $16, %rcx
1283         movdqa  %xmm4, %xmm3
1284         jmp     LABEL(loop_ashr_8)
1286         .p2align 4
1287 LABEL(nibble_ashr_8):
1288         pcmpeqb %xmm3, %xmm0            /* check nibble for null char */
1289         pmovmskb %xmm0, %edx
1290         test    $0xff00, %edx
1291         jnz     LABEL(ashr_8_exittail)
1293 # ifdef USE_AS_STRNCMP
1294         cmp     $7, %r11
1295         jbe     LABEL(ashr_8_exittail)
1296 # endif
1298         pxor    %xmm0, %xmm0
1299         sub     $0x1000, %r10
1300         jmp     LABEL(gobble_ashr_8)
1302         .p2align 4
1303 LABEL(ashr_8_exittail):
1304         movdqa  (%rsi, %rcx), %xmm1
1305         psrldq  $8, %xmm0
1306         psrldq  $8, %xmm3
1307         jmp     LABEL(aftertail)
1310  *  The following cases will be handled by ashr_9
1311  *  rcx(offset of rsi)  rax(offset of rdi)        relative offset        corresponding case
1312  *        n(7~15)          n - 7                8(15 +(n - 7) - n)         ashr_9
1313  */
1314         .p2align 4
1315 LABEL(ashr_9):
1316         pxor    %xmm0, %xmm0
1317         movdqa  (%rdi), %xmm2
1318         movdqa  (%rsi), %xmm1
1319         pcmpeqb %xmm1, %xmm0
1320         pslldq  $7, %xmm2
1321         TOLOWER (%xmm1, %xmm2)
1322         pcmpeqb %xmm1, %xmm2
1323         psubb   %xmm0, %xmm2
1324         pmovmskb %xmm2, %r9d
1325         shr     %cl, %edx
1326         shr     %cl, %r9d
1327         sub     %r9d, %edx
1328         jnz     LABEL(less32bytes)
1329         movdqa  (%rdi), %xmm3
1331         UPDATE_STRNCMP_COUNTER
1333         pxor    %xmm0, %xmm0
1334         mov     $16, %rcx       /* index for loads */
1335         mov     $9, %r9d        /* byte position left over from less32bytes case */
1336         /*
1337          * Setup %r10 value allows us to detect crossing a page boundary.
1338          * When %r10 goes positive we have crossed a page boundary and
1339          * need to do a nibble.
1340          */
1341         lea     9(%rdi), %r10
1342         and     $0xfff, %r10    /* offset into 4K page */
1343         sub     $0x1000, %r10   /* subtract 4K pagesize */
1345         .p2align 4
1346 LABEL(loop_ashr_9):
1347         add     $16, %r10
1348         jg      LABEL(nibble_ashr_9)
1350 LABEL(gobble_ashr_9):
1351         movdqa  (%rsi, %rcx), %xmm1
1352         movdqa  (%rdi, %rcx), %xmm2
1353         movdqa  %xmm2, %xmm4
1355 # ifndef USE_SSSE3
1356         psrldq  $9, %xmm3
1357         pslldq  $7, %xmm2
1358         por     %xmm3, %xmm2            /* merge into one 16byte value */
1359 # else
1360         palignr $9, %xmm3, %xmm2        /* merge into one 16byte value */
1361 # endif
1362         TOLOWER (%xmm1, %xmm2)
1364         pcmpeqb %xmm1, %xmm0
1365         pcmpeqb %xmm2, %xmm1
1366         psubb   %xmm0, %xmm1
1367         pmovmskb %xmm1, %edx
1368         sub     $0xffff, %edx
1369         jnz     LABEL(exit)
1371 # ifdef USE_AS_STRNCMP
1372         sub     $16, %r11
1373         jbe     LABEL(strcmp_exitz)
1374 # endif
1376         add     $16, %rcx
1377         movdqa  %xmm4, %xmm3
1379         add     $16, %r10
1380         jg      LABEL(nibble_ashr_9)    /* cross page boundary */
1382         movdqa  (%rsi, %rcx), %xmm1
1383         movdqa  (%rdi, %rcx), %xmm2
1384         movdqa  %xmm2, %xmm4
1386 # ifndef USE_SSSE3
1387         psrldq  $9, %xmm3
1388         pslldq  $7, %xmm2
1389         por     %xmm3, %xmm2            /* merge into one 16byte value */
1390 # else
1391         palignr $9, %xmm3, %xmm2        /* merge into one 16byte value */
1392 # endif
1393         TOLOWER (%xmm1, %xmm2)
1395         pcmpeqb %xmm1, %xmm0
1396         pcmpeqb %xmm2, %xmm1
1397         psubb   %xmm0, %xmm1
1398         pmovmskb %xmm1, %edx
1399         sub     $0xffff, %edx
1400         jnz     LABEL(exit)
1402 # ifdef USE_AS_STRNCMP
1403         sub     $16, %r11
1404         jbe     LABEL(strcmp_exitz)
1405 # endif
1407         add     $16, %rcx
1408         movdqa  %xmm4, %xmm3            /* store for next cycle */
1409         jmp     LABEL(loop_ashr_9)
1411         .p2align 4
1412 LABEL(nibble_ashr_9):
1413         pcmpeqb %xmm3, %xmm0            /* check nibble for null char */
1414         pmovmskb %xmm0, %edx
1415         test    $0xfe00, %edx
1416         jnz     LABEL(ashr_9_exittail)
1418 # ifdef USE_AS_STRNCMP
1419         cmp     $6, %r11
1420         jbe     LABEL(ashr_9_exittail)
1421 # endif
1423         pxor    %xmm0, %xmm0
1424         sub     $0x1000, %r10
1425         jmp     LABEL(gobble_ashr_9)
1427         .p2align 4
1428 LABEL(ashr_9_exittail):
1429         movdqa  (%rsi, %rcx), %xmm1
1430         psrldq  $9, %xmm0
1431         psrldq  $9, %xmm3
1432         jmp     LABEL(aftertail)
1435  *  The following cases will be handled by ashr_10
1436  *  rcx(offset of rsi)  rax(offset of rdi)        relative offset        corresponding case
1437  *        n(6~15)          n - 6                9(15 +(n - 6) - n)         ashr_10
1438  */
1439         .p2align 4
1440 LABEL(ashr_10):
1441         pxor    %xmm0, %xmm0
1442         movdqa  (%rdi), %xmm2
1443         movdqa  (%rsi), %xmm1
1444         pcmpeqb %xmm1, %xmm0
1445         pslldq  $6, %xmm2
1446         TOLOWER (%xmm1, %xmm2)
1447         pcmpeqb %xmm1, %xmm2
1448         psubb   %xmm0, %xmm2
1449         pmovmskb %xmm2, %r9d
1450         shr     %cl, %edx
1451         shr     %cl, %r9d
1452         sub     %r9d, %edx
1453         jnz     LABEL(less32bytes)
1454         movdqa  (%rdi), %xmm3
1456         UPDATE_STRNCMP_COUNTER
1458         pxor    %xmm0, %xmm0
1459         mov     $16, %rcx       /* index for loads */
1460         mov     $10, %r9d       /* byte position left over from less32bytes case */
1461         /*
1462          * Setup %r10 value allows us to detect crossing a page boundary.
1463          * When %r10 goes positive we have crossed a page boundary and
1464          * need to do a nibble.
1465          */
1466         lea     10(%rdi), %r10
1467         and     $0xfff, %r10    /* offset into 4K page */
1468         sub     $0x1000, %r10   /* subtract 4K pagesize */
1470         .p2align 4
1471 LABEL(loop_ashr_10):
1472         add     $16, %r10
1473         jg      LABEL(nibble_ashr_10)
1475 LABEL(gobble_ashr_10):
1476         movdqa  (%rsi, %rcx), %xmm1
1477         movdqa  (%rdi, %rcx), %xmm2
1478         movdqa  %xmm2, %xmm4
1480 # ifndef USE_SSSE3
1481         psrldq  $10, %xmm3
1482         pslldq  $6, %xmm2
1483         por     %xmm3, %xmm2            /* merge into one 16byte value */
1484 # else
1485         palignr $10, %xmm3, %xmm2       /* merge into one 16byte value */
1486 # endif
1487         TOLOWER (%xmm1, %xmm2)
1489         pcmpeqb %xmm1, %xmm0
1490         pcmpeqb %xmm2, %xmm1
1491         psubb   %xmm0, %xmm1
1492         pmovmskb %xmm1, %edx
1493         sub     $0xffff, %edx
1494         jnz     LABEL(exit)
1496 # ifdef USE_AS_STRNCMP
1497         sub     $16, %r11
1498         jbe     LABEL(strcmp_exitz)
1499 # endif
1501         add     $16, %rcx
1502         movdqa  %xmm4, %xmm3
1504         add     $16, %r10
1505         jg      LABEL(nibble_ashr_10)   /* cross page boundary */
1507         movdqa  (%rsi, %rcx), %xmm1
1508         movdqa  (%rdi, %rcx), %xmm2
1509         movdqa  %xmm2, %xmm4
1511 # ifndef USE_SSSE3
1512         psrldq  $10, %xmm3
1513         pslldq  $6, %xmm2
1514         por     %xmm3, %xmm2            /* merge into one 16byte value */
1515 # else
1516         palignr $10, %xmm3, %xmm2       /* merge into one 16byte value */
1517 # endif
1518         TOLOWER (%xmm1, %xmm2)
1520         pcmpeqb %xmm1, %xmm0
1521         pcmpeqb %xmm2, %xmm1
1522         psubb   %xmm0, %xmm1
1523         pmovmskb %xmm1, %edx
1524         sub     $0xffff, %edx
1525         jnz     LABEL(exit)
1527 # ifdef USE_AS_STRNCMP
1528         sub     $16, %r11
1529         jbe     LABEL(strcmp_exitz)
1530 # endif
1532         add     $16, %rcx
1533         movdqa  %xmm4, %xmm3
1534         jmp     LABEL(loop_ashr_10)
1536         .p2align 4
1537 LABEL(nibble_ashr_10):
1538         pcmpeqb %xmm3, %xmm0            /* check nibble for null char */
1539         pmovmskb %xmm0, %edx
1540         test    $0xfc00, %edx
1541         jnz     LABEL(ashr_10_exittail)
1543 # ifdef USE_AS_STRNCMP
1544         cmp     $5, %r11
1545         jbe     LABEL(ashr_10_exittail)
1546 # endif
1548         pxor    %xmm0, %xmm0
1549         sub     $0x1000, %r10
1550         jmp     LABEL(gobble_ashr_10)
1552         .p2align 4
1553 LABEL(ashr_10_exittail):
1554         movdqa  (%rsi, %rcx), %xmm1
1555         psrldq  $10, %xmm0
1556         psrldq  $10, %xmm3
1557         jmp     LABEL(aftertail)
1560  *  The following cases will be handled by ashr_11
1561  *  rcx(offset of rsi)  rax(offset of rdi)        relative offset        corresponding case
1562  *        n(5~15)          n - 5               10(15 +(n - 5) - n)         ashr_11
1563  */
1564         .p2align 4
1565 LABEL(ashr_11):
1566         pxor    %xmm0, %xmm0
1567         movdqa  (%rdi), %xmm2
1568         movdqa  (%rsi), %xmm1
1569         pcmpeqb %xmm1, %xmm0
1570         pslldq  $5, %xmm2
1571         TOLOWER (%xmm1, %xmm2)
1572         pcmpeqb %xmm1, %xmm2
1573         psubb   %xmm0, %xmm2
1574         pmovmskb %xmm2, %r9d
1575         shr     %cl, %edx
1576         shr     %cl, %r9d
1577         sub     %r9d, %edx
1578         jnz     LABEL(less32bytes)
1579         movdqa  (%rdi), %xmm3
1581         UPDATE_STRNCMP_COUNTER
1583         pxor    %xmm0, %xmm0
1584         mov     $16, %rcx       /* index for loads */
1585         mov     $11, %r9d       /* byte position left over from less32bytes case */
1586         /*
1587          * Setup %r10 value allows us to detect crossing a page boundary.
1588          * When %r10 goes positive we have crossed a page boundary and
1589          * need to do a nibble.
1590          */
1591         lea     11(%rdi), %r10
1592         and     $0xfff, %r10    /* offset into 4K page */
1593         sub     $0x1000, %r10   /* subtract 4K pagesize */
1595         .p2align 4
1596 LABEL(loop_ashr_11):
1597         add     $16, %r10
1598         jg      LABEL(nibble_ashr_11)
1600 LABEL(gobble_ashr_11):
1601         movdqa  (%rsi, %rcx), %xmm1
1602         movdqa  (%rdi, %rcx), %xmm2
1603         movdqa  %xmm2, %xmm4
1605 # ifndef USE_SSSE3
1606         psrldq  $11, %xmm3
1607         pslldq  $5, %xmm2
1608         por     %xmm3, %xmm2            /* merge into one 16byte value */
1609 # else
1610         palignr $11, %xmm3, %xmm2       /* merge into one 16byte value */
1611 # endif
1612         TOLOWER (%xmm1, %xmm2)
1614         pcmpeqb %xmm1, %xmm0
1615         pcmpeqb %xmm2, %xmm1
1616         psubb   %xmm0, %xmm1
1617         pmovmskb %xmm1, %edx
1618         sub     $0xffff, %edx
1619         jnz     LABEL(exit)
1621 # ifdef USE_AS_STRNCMP
1622         sub     $16, %r11
1623         jbe     LABEL(strcmp_exitz)
1624 # endif
1626         add     $16, %rcx
1627         movdqa  %xmm4, %xmm3
1629         add     $16, %r10
1630         jg      LABEL(nibble_ashr_11)   /* cross page boundary */
1632         movdqa  (%rsi, %rcx), %xmm1
1633         movdqa  (%rdi, %rcx), %xmm2
1634         movdqa  %xmm2, %xmm4
1636 # ifndef USE_SSSE3
1637         psrldq  $11, %xmm3
1638         pslldq  $5, %xmm2
1639         por     %xmm3, %xmm2            /* merge into one 16byte value */
1640 # else
1641         palignr $11, %xmm3, %xmm2       /* merge into one 16byte value */
1642 # endif
1643         TOLOWER (%xmm1, %xmm2)
1645         pcmpeqb %xmm1, %xmm0
1646         pcmpeqb %xmm2, %xmm1
1647         psubb   %xmm0, %xmm1
1648         pmovmskb %xmm1, %edx
1649         sub     $0xffff, %edx
1650         jnz     LABEL(exit)
1652 # ifdef USE_AS_STRNCMP
1653         sub     $16, %r11
1654         jbe     LABEL(strcmp_exitz)
1655 # endif
1657         add     $16, %rcx
1658         movdqa  %xmm4, %xmm3
1659         jmp     LABEL(loop_ashr_11)
1661         .p2align 4
1662 LABEL(nibble_ashr_11):
1663         pcmpeqb %xmm3, %xmm0            /* check nibble for null char */
1664         pmovmskb %xmm0, %edx
1665         test    $0xf800, %edx
1666         jnz     LABEL(ashr_11_exittail)
1668 # ifdef USE_AS_STRNCMP
1669         cmp     $4, %r11
1670         jbe     LABEL(ashr_11_exittail)
1671 # endif
1673         pxor    %xmm0, %xmm0
1674         sub     $0x1000, %r10
1675         jmp     LABEL(gobble_ashr_11)
1677         .p2align 4
1678 LABEL(ashr_11_exittail):
1679         movdqa  (%rsi, %rcx), %xmm1
1680         psrldq  $11, %xmm0
1681         psrldq  $11, %xmm3
1682         jmp     LABEL(aftertail)
1685  *  The following cases will be handled by ashr_12
1686  *  rcx(offset of rsi)  rax(offset of rdi)        relative offset        corresponding case
1687  *        n(4~15)          n - 4                11(15 +(n - 4) - n)         ashr_12
1688  */
1689         .p2align 4
1690 LABEL(ashr_12):
1691         pxor    %xmm0, %xmm0
1692         movdqa  (%rdi), %xmm2
1693         movdqa  (%rsi), %xmm1
1694         pcmpeqb %xmm1, %xmm0
1695         pslldq  $4, %xmm2
1696         TOLOWER (%xmm1, %xmm2)
1697         pcmpeqb %xmm1, %xmm2
1698         psubb   %xmm0, %xmm2
1699         pmovmskb %xmm2, %r9d
1700         shr     %cl, %edx
1701         shr     %cl, %r9d
1702         sub     %r9d, %edx
1703         jnz     LABEL(less32bytes)
1704         movdqa  (%rdi), %xmm3
1706         UPDATE_STRNCMP_COUNTER
1708         pxor    %xmm0, %xmm0
1709         mov     $16, %rcx       /* index for loads */
1710         mov     $12, %r9d       /* byte position left over from less32bytes case */
1711         /*
1712          * Setup %r10 value allows us to detect crossing a page boundary.
1713          * When %r10 goes positive we have crossed a page boundary and
1714          * need to do a nibble.
1715          */
1716         lea     12(%rdi), %r10
1717         and     $0xfff, %r10    /* offset into 4K page */
1718         sub     $0x1000, %r10   /* subtract 4K pagesize */
1720         .p2align 4
1721 LABEL(loop_ashr_12):
1722         add     $16, %r10
1723         jg      LABEL(nibble_ashr_12)
1725 LABEL(gobble_ashr_12):
1726         movdqa  (%rsi, %rcx), %xmm1
1727         movdqa  (%rdi, %rcx), %xmm2
1728         movdqa  %xmm2, %xmm4
1730 # ifndef USE_SSSE3
1731         psrldq  $12, %xmm3
1732         pslldq  $4, %xmm2
1733         por     %xmm3, %xmm2            /* merge into one 16byte value */
1734 # else
1735         palignr $12, %xmm3, %xmm2       /* merge into one 16byte value */
1736 # endif
1737         TOLOWER (%xmm1, %xmm2)
1739         pcmpeqb %xmm1, %xmm0
1740         pcmpeqb %xmm2, %xmm1
1741         psubb   %xmm0, %xmm1
1742         pmovmskb %xmm1, %edx
1743         sub     $0xffff, %edx
1744         jnz     LABEL(exit)
1746 # ifdef USE_AS_STRNCMP
1747         sub     $16, %r11
1748         jbe     LABEL(strcmp_exitz)
1749 # endif
1751         add     $16, %rcx
1752         movdqa  %xmm4, %xmm3
1754         add     $16, %r10
1755         jg      LABEL(nibble_ashr_12)   /* cross page boundary */
1757         movdqa  (%rsi, %rcx), %xmm1
1758         movdqa  (%rdi, %rcx), %xmm2
1759         movdqa  %xmm2, %xmm4
1761 # ifndef USE_SSSE3
1762         psrldq  $12, %xmm3
1763         pslldq  $4, %xmm2
1764         por     %xmm3, %xmm2            /* merge into one 16byte value */
1765 # else
1766         palignr $12, %xmm3, %xmm2       /* merge into one 16byte value */
1767 # endif
1768         TOLOWER (%xmm1, %xmm2)
1770         pcmpeqb %xmm1, %xmm0
1771         pcmpeqb %xmm2, %xmm1
1772         psubb   %xmm0, %xmm1
1773         pmovmskb %xmm1, %edx
1774         sub     $0xffff, %edx
1775         jnz     LABEL(exit)
1777 # ifdef USE_AS_STRNCMP
1778         sub     $16, %r11
1779         jbe     LABEL(strcmp_exitz)
1780 # endif
1782         add     $16, %rcx
1783         movdqa  %xmm4, %xmm3
1784         jmp     LABEL(loop_ashr_12)
1786         .p2align 4
1787 LABEL(nibble_ashr_12):
1788         pcmpeqb %xmm3, %xmm0            /* check nibble for null char */
1789         pmovmskb %xmm0, %edx
1790         test    $0xf000, %edx
1791         jnz     LABEL(ashr_12_exittail)
1793 # ifdef USE_AS_STRNCMP
1794         cmp     $3, %r11
1795         jbe     LABEL(ashr_12_exittail)
1796 # endif
1798         pxor    %xmm0, %xmm0
1799         sub     $0x1000, %r10
1800         jmp     LABEL(gobble_ashr_12)
1802         .p2align 4
1803 LABEL(ashr_12_exittail):
1804         movdqa  (%rsi, %rcx), %xmm1
1805         psrldq  $12, %xmm0
1806         psrldq  $12, %xmm3
1807         jmp     LABEL(aftertail)
1810  *  The following cases will be handled by ashr_13
1811  *  rcx(offset of rsi)  rax(offset of rdi)        relative offset        corresponding case
1812  *        n(3~15)          n - 3                12(15 +(n - 3) - n)         ashr_13
1813  */
1814         .p2align 4
1815 LABEL(ashr_13):
1816         pxor    %xmm0, %xmm0
1817         movdqa  (%rdi), %xmm2
1818         movdqa  (%rsi), %xmm1
1819         pcmpeqb %xmm1, %xmm0
1820         pslldq  $3, %xmm2
1821         TOLOWER (%xmm1, %xmm2)
1822         pcmpeqb %xmm1, %xmm2
1823         psubb   %xmm0, %xmm2
1824         pmovmskb %xmm2, %r9d
1825         shr     %cl, %edx
1826         shr     %cl, %r9d
1827         sub     %r9d, %edx
1828         jnz     LABEL(less32bytes)
1829         movdqa  (%rdi), %xmm3
1831         UPDATE_STRNCMP_COUNTER
1833         pxor    %xmm0, %xmm0
1834         mov     $16, %rcx       /* index for loads */
1835         mov     $13, %r9d       /* byte position left over from less32bytes case */
1836         /*
1837          * Setup %r10 value allows us to detect crossing a page boundary.
1838          * When %r10 goes positive we have crossed a page boundary and
1839          * need to do a nibble.
1840          */
1841         lea     13(%rdi), %r10
1842         and     $0xfff, %r10    /* offset into 4K page */
1843         sub     $0x1000, %r10   /* subtract 4K pagesize */
1845         .p2align 4
1846 LABEL(loop_ashr_13):
1847         add     $16, %r10
1848         jg      LABEL(nibble_ashr_13)
1850 LABEL(gobble_ashr_13):
1851         movdqa  (%rsi, %rcx), %xmm1
1852         movdqa  (%rdi, %rcx), %xmm2
1853         movdqa  %xmm2, %xmm4
1855 # ifndef USE_SSSE3
1856         psrldq  $13, %xmm3
1857         pslldq  $3, %xmm2
1858         por     %xmm3, %xmm2            /* merge into one 16byte value */
1859 # else
1860         palignr $13, %xmm3, %xmm2       /* merge into one 16byte value */
1861 # endif
1862         TOLOWER (%xmm1, %xmm2)
1864         pcmpeqb %xmm1, %xmm0
1865         pcmpeqb %xmm2, %xmm1
1866         psubb   %xmm0, %xmm1
1867         pmovmskb %xmm1, %edx
1868         sub     $0xffff, %edx
1869         jnz     LABEL(exit)
1871 # ifdef USE_AS_STRNCMP
1872         sub     $16, %r11
1873         jbe     LABEL(strcmp_exitz)
1874 # endif
1876         add     $16, %rcx
1877         movdqa  %xmm4, %xmm3
1879         add     $16, %r10
1880         jg      LABEL(nibble_ashr_13)   /* cross page boundary */
1882         movdqa  (%rsi, %rcx), %xmm1
1883         movdqa  (%rdi, %rcx), %xmm2
1884         movdqa  %xmm2, %xmm4
1886 # ifndef USE_SSSE3
1887         psrldq  $13, %xmm3
1888         pslldq  $3, %xmm2
1889         por     %xmm3, %xmm2            /* merge into one 16byte value */
1890 # else
1891         palignr $13, %xmm3, %xmm2       /* merge into one 16byte value */
1892 # endif
1893         TOLOWER (%xmm1, %xmm2)
1895         pcmpeqb %xmm1, %xmm0
1896         pcmpeqb %xmm2, %xmm1
1897         psubb   %xmm0, %xmm1
1898         pmovmskb %xmm1, %edx
1899         sub     $0xffff, %edx
1900         jnz     LABEL(exit)
1902 # ifdef USE_AS_STRNCMP
1903         sub     $16, %r11
1904         jbe     LABEL(strcmp_exitz)
1905 # endif
1907         add     $16, %rcx
1908         movdqa  %xmm4, %xmm3
1909         jmp     LABEL(loop_ashr_13)
1911         .p2align 4
1912 LABEL(nibble_ashr_13):
1913         pcmpeqb %xmm3, %xmm0            /* check nibble for null char */
1914         pmovmskb %xmm0, %edx
1915         test    $0xe000, %edx
1916         jnz     LABEL(ashr_13_exittail)
1918 # ifdef USE_AS_STRNCMP
1919         cmp     $2, %r11
1920         jbe     LABEL(ashr_13_exittail)
1921 # endif
1923         pxor    %xmm0, %xmm0
1924         sub     $0x1000, %r10
1925         jmp     LABEL(gobble_ashr_13)
1927         .p2align 4
1928 LABEL(ashr_13_exittail):
1929         movdqa  (%rsi, %rcx), %xmm1
1930         psrldq  $13, %xmm0
1931         psrldq  $13, %xmm3
1932         jmp     LABEL(aftertail)
1935  *  The following cases will be handled by ashr_14
1936  *  rcx(offset of rsi)  rax(offset of rdi)        relative offset        corresponding case
1937  *        n(2~15)          n - 2                13(15 +(n - 2) - n)         ashr_14
1938  */
1939         .p2align 4
1940 LABEL(ashr_14):
1941         pxor    %xmm0, %xmm0
1942         movdqa  (%rdi), %xmm2
1943         movdqa  (%rsi), %xmm1
1944         pcmpeqb %xmm1, %xmm0
1945         pslldq  $2, %xmm2
1946         TOLOWER (%xmm1, %xmm2)
1947         pcmpeqb %xmm1, %xmm2
1948         psubb   %xmm0, %xmm2
1949         pmovmskb %xmm2, %r9d
1950         shr     %cl, %edx
1951         shr     %cl, %r9d
1952         sub     %r9d, %edx
1953         jnz     LABEL(less32bytes)
1954         movdqa  (%rdi), %xmm3
1956         UPDATE_STRNCMP_COUNTER
1958         pxor    %xmm0, %xmm0
1959         mov     $16, %rcx       /* index for loads */
1960         mov     $14, %r9d       /* byte position left over from less32bytes case */
1961         /*
1962          * Setup %r10 value allows us to detect crossing a page boundary.
1963          * When %r10 goes positive we have crossed a page boundary and
1964          * need to do a nibble.
1965          */
1966         lea     14(%rdi), %r10
1967         and     $0xfff, %r10    /* offset into 4K page */
1968         sub     $0x1000, %r10   /* subtract 4K pagesize */
1970         .p2align 4
1971 LABEL(loop_ashr_14):
1972         add     $16, %r10
1973         jg      LABEL(nibble_ashr_14)
1975 LABEL(gobble_ashr_14):
1976         movdqa  (%rsi, %rcx), %xmm1
1977         movdqa  (%rdi, %rcx), %xmm2
1978         movdqa  %xmm2, %xmm4
1980 # ifndef USE_SSSE3
1981         psrldq  $14, %xmm3
1982         pslldq  $2, %xmm2
1983         por     %xmm3, %xmm2            /* merge into one 16byte value */
1984 # else
1985         palignr $14, %xmm3, %xmm2       /* merge into one 16byte value */
1986 # endif
1987         TOLOWER (%xmm1, %xmm2)
1989         pcmpeqb %xmm1, %xmm0
1990         pcmpeqb %xmm2, %xmm1
1991         psubb   %xmm0, %xmm1
1992         pmovmskb %xmm1, %edx
1993         sub     $0xffff, %edx
1994         jnz     LABEL(exit)
1996 # ifdef USE_AS_STRNCMP
1997         sub     $16, %r11
1998         jbe     LABEL(strcmp_exitz)
1999 # endif
2001         add     $16, %rcx
2002         movdqa  %xmm4, %xmm3
2004         add     $16, %r10
2005         jg      LABEL(nibble_ashr_14)   /* cross page boundary */
2007         movdqa  (%rsi, %rcx), %xmm1
2008         movdqa  (%rdi, %rcx), %xmm2
2009         movdqa  %xmm2, %xmm4
2011 # ifndef USE_SSSE3
2012         psrldq  $14, %xmm3
2013         pslldq  $2, %xmm2
2014         por     %xmm3, %xmm2            /* merge into one 16byte value */
2015 # else
2016         palignr $14, %xmm3, %xmm2       /* merge into one 16byte value */
2017 # endif
2018         TOLOWER (%xmm1, %xmm2)
2020         pcmpeqb %xmm1, %xmm0
2021         pcmpeqb %xmm2, %xmm1
2022         psubb   %xmm0, %xmm1
2023         pmovmskb %xmm1, %edx
2024         sub     $0xffff, %edx
2025         jnz     LABEL(exit)
2027 # ifdef USE_AS_STRNCMP
2028         sub     $16, %r11
2029         jbe     LABEL(strcmp_exitz)
2030 # endif
2032         add     $16, %rcx
2033         movdqa  %xmm4, %xmm3
2034         jmp     LABEL(loop_ashr_14)
2036         .p2align 4
2037 LABEL(nibble_ashr_14):
2038         pcmpeqb %xmm3, %xmm0            /* check nibble for null char */
2039         pmovmskb %xmm0, %edx
2040         test    $0xc000, %edx
2041         jnz     LABEL(ashr_14_exittail)
2043 # ifdef USE_AS_STRNCMP
2044         cmp     $1, %r11
2045         jbe     LABEL(ashr_14_exittail)
2046 # endif
2048         pxor    %xmm0, %xmm0
2049         sub     $0x1000, %r10
2050         jmp     LABEL(gobble_ashr_14)
2052         .p2align 4
2053 LABEL(ashr_14_exittail):
2054         movdqa  (%rsi, %rcx), %xmm1
2055         psrldq  $14, %xmm0
2056         psrldq  $14, %xmm3
2057         jmp     LABEL(aftertail)
2060  *  The following cases will be handled by ashr_15
2061  *  rcx(offset of rsi)  rax(offset of rdi)        relative offset        corresponding case
2062  *        n(1~15)          n - 1                14(15 +(n - 1) - n)         ashr_15
2063  */
2064         .p2align 4
2065 LABEL(ashr_15):
2066         pxor    %xmm0, %xmm0
2067         movdqa  (%rdi), %xmm2
2068         movdqa  (%rsi), %xmm1
2069         pcmpeqb %xmm1, %xmm0
2070         pslldq  $1, %xmm2
2071         TOLOWER (%xmm1, %xmm2)
2072         pcmpeqb %xmm1, %xmm2
2073         psubb   %xmm0, %xmm2
2074         pmovmskb %xmm2, %r9d
2075         shr     %cl, %edx
2076         shr     %cl, %r9d
2077         sub     %r9d, %edx
2078         jnz     LABEL(less32bytes)
2080         movdqa  (%rdi), %xmm3
2082         UPDATE_STRNCMP_COUNTER
2084         pxor    %xmm0, %xmm0
2085         mov     $16, %rcx       /* index for loads */
2086         mov     $15, %r9d       /* byte position left over from less32bytes case */
2087         /*
2088          * Setup %r10 value allows us to detect crossing a page boundary.
2089          * When %r10 goes positive we have crossed a page boundary and
2090          * need to do a nibble.
2091          */
2092         lea     15(%rdi), %r10
2093         and     $0xfff, %r10    /* offset into 4K page */
2095         sub     $0x1000, %r10   /* subtract 4K pagesize */
2097         .p2align 4
2098 LABEL(loop_ashr_15):
2099         add     $16, %r10
2100         jg      LABEL(nibble_ashr_15)
2102 LABEL(gobble_ashr_15):
2103         movdqa  (%rsi, %rcx), %xmm1
2104         movdqa  (%rdi, %rcx), %xmm2
2105         movdqa  %xmm2, %xmm4
2107 # ifndef USE_SSSE3
2108         psrldq  $15, %xmm3
2109         pslldq  $1, %xmm2
2110         por     %xmm3, %xmm2            /* merge into one 16byte value */
2111 # else
2112         palignr $15, %xmm3, %xmm2       /* merge into one 16byte value */
2113 # endif
2114         TOLOWER (%xmm1, %xmm2)
2116         pcmpeqb %xmm1, %xmm0
2117         pcmpeqb %xmm2, %xmm1
2118         psubb   %xmm0, %xmm1
2119         pmovmskb %xmm1, %edx
2120         sub     $0xffff, %edx
2121         jnz     LABEL(exit)
2123 # ifdef USE_AS_STRNCMP
2124         sub     $16, %r11
2125         jbe     LABEL(strcmp_exitz)
2126 # endif
2128         add     $16, %rcx
2129         movdqa  %xmm4, %xmm3
2131         add     $16, %r10
2132         jg      LABEL(nibble_ashr_15)   /* cross page boundary */
2134         movdqa  (%rsi, %rcx), %xmm1
2135         movdqa  (%rdi, %rcx), %xmm2
2136         movdqa  %xmm2, %xmm4
2138 # ifndef USE_SSSE3
2139         psrldq  $15, %xmm3
2140         pslldq  $1, %xmm2
2141         por     %xmm3, %xmm2            /* merge into one 16byte value */
2142 # else
2143         palignr $15, %xmm3, %xmm2       /* merge into one 16byte value */
2144 # endif
2145         TOLOWER (%xmm1, %xmm2)
2147         pcmpeqb %xmm1, %xmm0
2148         pcmpeqb %xmm2, %xmm1
2149         psubb   %xmm0, %xmm1
2150         pmovmskb %xmm1, %edx
2151         sub     $0xffff, %edx
2152         jnz     LABEL(exit)
2154 # ifdef USE_AS_STRNCMP
2155         sub     $16, %r11
2156         jbe     LABEL(strcmp_exitz)
2157 # endif
2159         add     $16, %rcx
2160         movdqa  %xmm4, %xmm3
2161         jmp     LABEL(loop_ashr_15)
2163         .p2align 4
2164 LABEL(nibble_ashr_15):
2165         pcmpeqb %xmm3, %xmm0            /* check nibble for null char */
2166         pmovmskb %xmm0, %edx
2167         test    $0x8000, %edx
2168         jnz     LABEL(ashr_15_exittail)
2170 # ifdef USE_AS_STRNCMP
2171         test    %r11, %r11
2172         je      LABEL(ashr_15_exittail)
2173 # endif
2175         pxor    %xmm0, %xmm0
2176         sub     $0x1000, %r10
2177         jmp     LABEL(gobble_ashr_15)
2179         .p2align 4
2180 LABEL(ashr_15_exittail):
2181         movdqa  (%rsi, %rcx), %xmm1
2182         psrldq  $15, %xmm3
2183         psrldq  $15, %xmm0
2185         .p2align 4
2186 LABEL(aftertail):
2187         TOLOWER (%xmm1, %xmm3)
2188         pcmpeqb %xmm3, %xmm1
2189         psubb   %xmm0, %xmm1
2190         pmovmskb %xmm1, %edx
2191         not     %edx
2193         .p2align 4
2194 LABEL(exit):
2195         lea     -16(%r9, %rcx), %rax    /* locate the exact offset for rdi */
2196 LABEL(less32bytes):
2197         lea     (%rdi, %rax), %rdi      /* locate the exact address for first operand(rdi) */
2198         lea     (%rsi, %rcx), %rsi      /* locate the exact address for second operand(rsi) */
2199         test    %r8d, %r8d
2200         jz      LABEL(ret)
2201         xchg    %rsi, %rdi              /* recover original order according to flag(%r8d) */
2203         .p2align 4
2204 LABEL(ret):
2205 LABEL(less16bytes):
2206         bsf     %rdx, %rdx              /* find and store bit index in %rdx */
2208 # ifdef USE_AS_STRNCMP
2209         sub     %rdx, %r11
2210         jbe     LABEL(strcmp_exitz)
2211 # endif
2212         movzbl  (%rsi, %rdx), %ecx
2213         movzbl  (%rdi, %rdx), %eax
2215 # ifdef USE_AS_STRCASECMP_L
2216         leaq    _nl_C_LC_CTYPE_tolower+128*4(%rip), %rdx
2217         movl    (%rdx,%rcx,4), %ecx
2218         movl    (%rdx,%rax,4), %eax
2219 # endif
2221         sub     %ecx, %eax
2222         ret
2224 LABEL(strcmp_exitz):
2225         xor     %eax, %eax
2226         ret
2228         .p2align 4
2229 LABEL(Byte0):
2230         movzx   (%rsi), %ecx
2231         movzx   (%rdi), %eax
2233         sub     %ecx, %eax
2234         ret
2235 END (BP_SYM (STRCMP))
2237         .section .rodata,"a",@progbits
2238         .p2align 3
2239 LABEL(unaligned_table):
2240         .int    LABEL(ashr_1) - LABEL(unaligned_table)
2241         .int    LABEL(ashr_2) - LABEL(unaligned_table)
2242         .int    LABEL(ashr_3) - LABEL(unaligned_table)
2243         .int    LABEL(ashr_4) - LABEL(unaligned_table)
2244         .int    LABEL(ashr_5) - LABEL(unaligned_table)
2245         .int    LABEL(ashr_6) - LABEL(unaligned_table)
2246         .int    LABEL(ashr_7) - LABEL(unaligned_table)
2247         .int    LABEL(ashr_8) - LABEL(unaligned_table)
2248         .int    LABEL(ashr_9) - LABEL(unaligned_table)
2249         .int    LABEL(ashr_10) - LABEL(unaligned_table)
2250         .int    LABEL(ashr_11) - LABEL(unaligned_table)
2251         .int    LABEL(ashr_12) - LABEL(unaligned_table)
2252         .int    LABEL(ashr_13) - LABEL(unaligned_table)
2253         .int    LABEL(ashr_14) - LABEL(unaligned_table)
2254         .int    LABEL(ashr_15) - LABEL(unaligned_table)
2255         .int    LABEL(ashr_0) - LABEL(unaligned_table)
2256 #endif /* NOT_IN_libc */
2257 libc_hidden_builtin_def (STRCMP)