Define bit_SSE2 and index_SSE2.
[glibc.git] / sysdeps / x86_64 / strcmp.S
blob650ec173b6a1dc0655d0e0fc58a2a0352987ff5b
1 /* Highly optimized version for x86-64.
2    Copyright (C) 1999, 2000, 2002, 2003, 2005, 2009
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 /* Since the counter, %r11, is unsigned, we branch to strcmp_exitz
37    if the new counter > the old one or is 0.  */
38 # define UPDATE_STRNCMP_COUNTER                         \
39         /* calculate left number to compare */          \
40         lea     -16(%rcx, %r11), %r9;                   \
41         cmp     %r9, %r11;                              \
42         jb      LABEL(strcmp_exitz);                    \
43         test    %r9, %r9;                               \
44         je      LABEL(strcmp_exitz);                    \
45         mov     %r9, %r11
47 #else
48 # define UPDATE_STRNCMP_COUNTER
49 # ifndef STRCMP
50 #  define STRCMP strcmp
51 # endif
52 #endif
54 #ifndef USE_SSSE3
55         .text
56 #else
57         .section .text.ssse3,"ax",@progbits
58 #endif
60 ENTRY (BP_SYM (STRCMP))
61 #ifdef NOT_IN_libc
62 /* Simple version since we can't use SSE registers in ld.so.  */
63 L(oop): movb    (%rdi), %al
64         cmpb    (%rsi), %al
65         jne     L(neq)
66         incq    %rdi
67         incq    %rsi
68         testb   %al, %al
69         jnz     L(oop)
71         xorl    %eax, %eax
72         ret
74 L(neq): movl    $1, %eax
75         movl    $-1, %ecx
76         cmovbl  %ecx, %eax
77         ret
78 END (BP_SYM (STRCMP))
79 #else   /* NOT_IN_libc */
81  * This implementation uses SSE to compare up to 16 bytes at a time.
82  */
83 #ifdef USE_AS_STRNCMP
84         test    %rdx, %rdx
85         je      LABEL(strcmp_exitz)
86         cmp     $1, %rdx
87         je      LABEL(Byte0)
88         mov     %rdx, %r11
89 #endif
90         mov     %esi, %ecx
91         mov     %edi, %eax
92 /* Use 64bit AND here to avoid long NOP padding.  */
93         and     $0x3f, %rcx             /* rsi alignment in cache line */
94         and     $0x3f, %rax             /* rdi alignment in cache line */
95         cmp     $0x30, %ecx
96         ja      LABEL(crosscache)       /* rsi: 16-byte load will cross cache line */
97         cmp     $0x30, %eax
98         ja      LABEL(crosscache)       /* rdi: 16-byte load will cross cache line */
99         movlpd  (%rdi), %xmm1
100         movlpd  (%rsi), %xmm2
101         movhpd  8(%rdi), %xmm1
102         movhpd  8(%rsi), %xmm2
103         pxor    %xmm0, %xmm0            /* clear %xmm0 for null char checks */
104         pcmpeqb %xmm1, %xmm0            /* Any null chars? */
105         pcmpeqb %xmm2, %xmm1            /* compare first 16 bytes for equality */
106         psubb   %xmm0, %xmm1            /* packed sub of comparison results*/
107         pmovmskb %xmm1, %edx
108         sub     $0xffff, %edx           /* if first 16 bytes are same, edx == 0xffff */
109         jnz     LABEL(less16bytes)      /* If not, find different value or null char */
110 #ifdef USE_AS_STRNCMP
111         sub     $16, %r11
112         jbe     LABEL(strcmp_exitz)     /* finish comparision */
113 #endif
114         add     $16, %rsi               /* prepare to search next 16 bytes */
115         add     $16, %rdi               /* prepare to search next 16 bytes */
117         /*
118          * Determine source and destination string offsets from 16-byte alignment.
119          * Use relative offset difference between the two to determine which case
120          * below to use.
121          */
122         .p2align 4
123 LABEL(crosscache):
124         and     $0xfffffffffffffff0, %rsi       /* force %rsi is 16 byte aligned */
125         and     $0xfffffffffffffff0, %rdi       /* force %rdi is 16 byte aligned */
126         mov     $0xffff, %edx                   /* for equivalent offset */
127         xor     %r8d, %r8d
128         and     $0xf, %ecx                      /* offset of rsi */
129         and     $0xf, %eax                      /* offset of rdi */
130         cmp     %eax, %ecx
131         je      LABEL(ashr_0)                   /* rsi and rdi relative offset same */
132         ja      LABEL(bigger)
133         mov     %edx, %r8d                      /* r8d is offset flag for exit tail */
134         xchg    %ecx, %eax
135         xchg    %rsi, %rdi
136 LABEL(bigger):
137         lea     15(%rax), %r9
138         sub     %rcx, %r9
139         lea     LABEL(unaligned_table)(%rip), %r10
140         movslq  (%r10, %r9,4), %r9
141         lea     (%r10, %r9), %r10
142         jmp     *%r10                           /* jump to corresponding case */
145  * The following cases will be handled by ashr_0
146  *  rcx(offset of rsi)  rax(offset of rdi)  relative offset  corresponding case
147  *        n(0~15)            n(0~15)           15(15+ n-n)         ashr_0
148  */
149         .p2align 4
150 LABEL(ashr_0):
152         movdqa  (%rsi), %xmm1
153         pxor    %xmm0, %xmm0                    /* clear %xmm0 for null char check */
154         pcmpeqb %xmm1, %xmm0                    /* Any null chars? */
155         pcmpeqb (%rdi), %xmm1                   /* compare 16 bytes for equality */
156         psubb   %xmm0, %xmm1                    /* packed sub of comparison results*/
157         pmovmskb %xmm1, %r9d
158         shr     %cl, %edx                       /* adjust 0xffff for offset */
159         shr     %cl, %r9d                       /* adjust for 16-byte offset */
160         sub     %r9d, %edx
161         /*
162          * edx must be the same with r9d if in left byte (16-rcx) is equal to
163          * the start from (16-rax) and no null char was seen.
164          */
165         jne     LABEL(less32bytes)              /* mismatch or null char */
166         UPDATE_STRNCMP_COUNTER
167         mov     $16, %rcx
168         mov     $16, %r9
169         pxor    %xmm0, %xmm0                    /* clear xmm0, may have changed above */
171         /*
172          * Now both strings are aligned at 16-byte boundary. Loop over strings
173          * checking 32-bytes per iteration.
174          */
175         .p2align 4
176 LABEL(loop_ashr_0):
177         movdqa  (%rsi, %rcx), %xmm1
178         movdqa  (%rdi, %rcx), %xmm2
180         pcmpeqb %xmm1, %xmm0
181         pcmpeqb %xmm2, %xmm1
182         psubb   %xmm0, %xmm1
183         pmovmskb %xmm1, %edx
184         sub     $0xffff, %edx
185         jnz     LABEL(exit)             /* mismatch or null char seen */
187 #ifdef USE_AS_STRNCMP
188         sub     $16, %r11
189         jbe     LABEL(strcmp_exitz)
190 #endif
191         add     $16, %rcx
192         movdqa  (%rsi, %rcx), %xmm1
193         movdqa  (%rdi, %rcx), %xmm2
195         pcmpeqb %xmm1, %xmm0
196         pcmpeqb %xmm2, %xmm1
197         psubb   %xmm0, %xmm1
198         pmovmskb %xmm1, %edx
199         sub     $0xffff, %edx
200         jnz     LABEL(exit)
201 #ifdef USE_AS_STRNCMP
202         sub     $16, %r11
203         jbe     LABEL(strcmp_exitz)
204 #endif
205         add     $16, %rcx
206         jmp     LABEL(loop_ashr_0)
209  * The following cases will be handled by ashr_1
210  * rcx(offset of rsi)  rax(offset of rdi)   relative offset     corresponding case
211  *        n(15)            n -15            0(15 +(n-15) - n)         ashr_1
212  */
213         .p2align 4
214 LABEL(ashr_1):
215         pxor    %xmm0, %xmm0
216         movdqa  (%rdi), %xmm2
217         movdqa  (%rsi), %xmm1
218         pcmpeqb %xmm1, %xmm0            /* Any null chars? */
219         pslldq  $15, %xmm2              /* shift first string to align with second */
220         pcmpeqb %xmm1, %xmm2            /* compare 16 bytes for equality */
221         psubb   %xmm0, %xmm2            /* packed sub of comparison results*/
222         pmovmskb %xmm2, %r9d
223         shr     %cl, %edx               /* adjust 0xffff for offset */
224         shr     %cl, %r9d               /* adjust for 16-byte offset */
225         sub     %r9d, %edx
226         jnz     LABEL(less32bytes)      /* mismatch or null char seen */
227         movdqa  (%rdi), %xmm3
228         UPDATE_STRNCMP_COUNTER
230         pxor    %xmm0, %xmm0
231         mov     $16, %rcx               /* index for loads*/
232         mov     $1, %r9d                /* byte position left over from less32bytes case */
233         /*
234          * Setup %r10 value allows us to detect crossing a page boundary.
235          * When %r10 goes positive we have crossed a page boundary and
236          * need to do a nibble.
237          */
238         lea     1(%rdi), %r10
239         and     $0xfff, %r10            /* offset into 4K page */
240         sub     $0x1000, %r10           /* subtract 4K pagesize */
242         .p2align 4
243 LABEL(loop_ashr_1):
244         add     $16, %r10
245         jg      LABEL(nibble_ashr_1)    /* cross page boundary */
247 LABEL(gobble_ashr_1):
248         movdqa  (%rsi, %rcx), %xmm1
249         movdqa  (%rdi, %rcx), %xmm2
250         movdqa  %xmm2, %xmm4             /* store for next cycle */
252 #ifndef USE_SSSE3
253         psrldq  $1, %xmm3
254         pslldq  $15, %xmm2
255         por     %xmm3, %xmm2            /* merge into one 16byte value */
256 #else
257         palignr $1, %xmm3, %xmm2        /* merge into one 16byte value */
258 #endif
260         pcmpeqb %xmm1, %xmm0
261         pcmpeqb %xmm2, %xmm1
262         psubb   %xmm0, %xmm1
263         pmovmskb %xmm1, %edx
264         sub     $0xffff, %edx
265         jnz     LABEL(exit)
267 #ifdef USE_AS_STRNCMP
268         sub     $16, %r11
269         jbe     LABEL(strcmp_exitz)
270 #endif
271         add     $16, %rcx
272         movdqa  %xmm4, %xmm3
274         add     $16, %r10
275         jg      LABEL(nibble_ashr_1)    /* cross page boundary */
277         movdqa  (%rsi, %rcx), %xmm1
278         movdqa  (%rdi, %rcx), %xmm2
279         movdqa  %xmm2, %xmm4            /* store for next cycle */
281 #ifndef USE_SSSE3
282         psrldq  $1, %xmm3
283         pslldq  $15, %xmm2
284         por     %xmm3, %xmm2            /* merge into one 16byte value */
285 #else
286         palignr $1, %xmm3, %xmm2        /* merge into one 16byte value */
287 #endif
289         pcmpeqb %xmm1, %xmm0
290         pcmpeqb %xmm2, %xmm1
291         psubb   %xmm0, %xmm1
292         pmovmskb %xmm1, %edx
293         sub     $0xffff, %edx
294         jnz     LABEL(exit)
296 #ifdef USE_AS_STRNCMP
297         sub     $16, %r11
298         jbe     LABEL(strcmp_exitz)
299 #endif
300         add     $16, %rcx
301         movdqa  %xmm4, %xmm3
302         jmp     LABEL(loop_ashr_1)
304         /*
305          * Nibble avoids loads across page boundary. This is to avoid a potential
306          * access into unmapped memory.
307          */
308         .p2align 4
309 LABEL(nibble_ashr_1):
310         pcmpeqb %xmm3, %xmm0             /* check nibble for null char*/
311         pmovmskb %xmm0, %edx
312         test    $0xfffe, %edx
313         jnz     LABEL(ashr_1_exittail)  /* find null char*/
315 #ifdef USE_AS_STRNCMP
316         cmp     $14, %r11
317         jbe     LABEL(ashr_1_exittail)
318 #endif
320         pxor    %xmm0, %xmm0
321         sub     $0x1000, %r10           /* substract 4K from %r10 */
322         jmp     LABEL(gobble_ashr_1)
324         /*
325          * Once find null char, determine if there is a string mismatch
326          * before the null char.
327          */
328         .p2align 4
329 LABEL(ashr_1_exittail):
330         movdqa  (%rsi, %rcx), %xmm1
331         psrldq  $1, %xmm0
332         psrldq  $1, %xmm3
333         jmp     LABEL(aftertail)
336  * The following cases will be handled by ashr_2
337  * rcx(offset of rsi)  rax(offset of rdi)   relative offset     corresponding case
338  *        n(14~15)            n -14         1(15 +(n-14) - n)         ashr_2
339  */
340         .p2align 4
341 LABEL(ashr_2):
342         pxor    %xmm0, %xmm0
343         movdqa  (%rdi), %xmm2
344         movdqa  (%rsi), %xmm1
345         pcmpeqb %xmm1, %xmm0
346         pslldq  $14, %xmm2
347         pcmpeqb %xmm1, %xmm2
348         psubb   %xmm0, %xmm2
349         pmovmskb %xmm2, %r9d
350         shr     %cl, %edx
351         shr     %cl, %r9d
352         sub     %r9d, %edx
353         jnz     LABEL(less32bytes)
354         movdqa  (%rdi), %xmm3
355         UPDATE_STRNCMP_COUNTER
357         pxor    %xmm0, %xmm0
358         mov     $16, %rcx       /* index for loads */
359         mov     $2, %r9d        /* byte position left over from less32bytes case */
360         /*
361          * Setup %r10 value allows us to detect crossing a page boundary.
362          * When %r10 goes positive we have crossed a page boundary and
363          * need to do a nibble.
364          */
365         lea     2(%rdi), %r10
366         and     $0xfff, %r10    /* offset into 4K page */
367         sub     $0x1000, %r10   /* subtract 4K pagesize */
369         .p2align 4
370 LABEL(loop_ashr_2):
371         add     $16, %r10
372         jg      LABEL(nibble_ashr_2)
374 LABEL(gobble_ashr_2):
375         movdqa  (%rsi, %rcx), %xmm1
376         movdqa  (%rdi, %rcx), %xmm2
377         movdqa  %xmm2, %xmm4
379 #ifndef USE_SSSE3
380         psrldq  $2, %xmm3
381         pslldq  $14, %xmm2
382         por     %xmm3, %xmm2            /* merge into one 16byte value */
383 #else
384         palignr $2, %xmm3, %xmm2        /* merge into one 16byte value */
385 #endif
387         pcmpeqb %xmm1, %xmm0
388         pcmpeqb %xmm2, %xmm1
389         psubb   %xmm0, %xmm1
390         pmovmskb %xmm1, %edx
391         sub     $0xffff, %edx
392         jnz     LABEL(exit)
394 #ifdef USE_AS_STRNCMP
395         sub     $16, %r11
396         jbe     LABEL(strcmp_exitz)
397 #endif
399         add     $16, %rcx
400         movdqa  %xmm4, %xmm3
402         add     $16, %r10
403         jg      LABEL(nibble_ashr_2)    /* cross page boundary */
405         movdqa  (%rsi, %rcx), %xmm1
406         movdqa  (%rdi, %rcx), %xmm2
407         movdqa  %xmm2, %xmm4
409 #ifndef USE_SSSE3
410         psrldq  $2, %xmm3
411         pslldq  $14, %xmm2
412         por     %xmm3, %xmm2            /* merge into one 16byte value */
413 #else
414         palignr $2, %xmm3, %xmm2        /* merge into one 16byte value */
415 #endif
417         pcmpeqb %xmm1, %xmm0
418         pcmpeqb %xmm2, %xmm1
419         psubb   %xmm0, %xmm1
420         pmovmskb %xmm1, %edx
421         sub     $0xffff, %edx
422         jnz     LABEL(exit)
424 #ifdef USE_AS_STRNCMP
425         sub     $16, %r11
426         jbe     LABEL(strcmp_exitz)
427 #endif
429         add     $16, %rcx
430         movdqa  %xmm4, %xmm3
431         jmp     LABEL(loop_ashr_2)
433         .p2align 4
434 LABEL(nibble_ashr_2):
435         pcmpeqb %xmm3, %xmm0            /* check nibble for null char */
436         pmovmskb %xmm0, %edx
437         test    $0xfffc, %edx
438         jnz     LABEL(ashr_2_exittail)
440 #ifdef USE_AS_STRNCMP
441         cmp     $13, %r11
442         jbe     LABEL(ashr_2_exittail)
443 #endif
445         pxor    %xmm0, %xmm0
446         sub     $0x1000, %r10
447         jmp     LABEL(gobble_ashr_2)
449         .p2align 4
450 LABEL(ashr_2_exittail):
451         movdqa  (%rsi, %rcx), %xmm1
452         psrldq  $2, %xmm0
453         psrldq  $2, %xmm3
454         jmp     LABEL(aftertail)
457  * The following cases will be handled by ashr_3
458  *  rcx(offset of rsi)  rax(offset of rdi)  relative offset      corresponding case
459  *        n(13~15)            n -13         2(15 +(n-13) - n)         ashr_3
460  */
461         .p2align 4
462 LABEL(ashr_3):
463         pxor    %xmm0, %xmm0
464         movdqa  (%rdi), %xmm2
465         movdqa  (%rsi), %xmm1
466         pcmpeqb %xmm1, %xmm0
467         pslldq  $13, %xmm2
468         pcmpeqb %xmm1, %xmm2
469         psubb   %xmm0, %xmm2
470         pmovmskb %xmm2, %r9d
471         shr     %cl, %edx
472         shr     %cl, %r9d
473         sub     %r9d, %edx
474         jnz     LABEL(less32bytes)
475         movdqa  (%rdi), %xmm3
477         UPDATE_STRNCMP_COUNTER
479         pxor    %xmm0, %xmm0
480         mov     $16, %rcx       /* index for loads */
481         mov     $3, %r9d        /* byte position left over from less32bytes case */
482         /*
483          * Setup %r10 value allows us to detect crossing a page boundary.
484          * When %r10 goes positive we have crossed a page boundary and
485          * need to do a nibble.
486          */
487         lea     3(%rdi), %r10
488         and     $0xfff, %r10    /* offset into 4K page */
489         sub     $0x1000, %r10   /* subtract 4K pagesize */
491         .p2align 4
492 LABEL(loop_ashr_3):
493         add     $16, %r10
494         jg      LABEL(nibble_ashr_3)
496 LABEL(gobble_ashr_3):
497         movdqa  (%rsi, %rcx), %xmm1
498         movdqa  (%rdi, %rcx), %xmm2
499         movdqa  %xmm2, %xmm4
501 #ifndef USE_SSSE3
502         psrldq  $3, %xmm3
503         pslldq  $13, %xmm2
504         por     %xmm3, %xmm2            /* merge into one 16byte value */
505 #else
506         palignr $3, %xmm3, %xmm2        /* merge into one 16byte value */
507 #endif
509         pcmpeqb %xmm1, %xmm0
510         pcmpeqb %xmm2, %xmm1
511         psubb   %xmm0, %xmm1
512         pmovmskb %xmm1, %edx
513         sub     $0xffff, %edx
514         jnz     LABEL(exit)
516 #ifdef USE_AS_STRNCMP
517         sub     $16, %r11
518         jbe     LABEL(strcmp_exitz)
519 #endif
521         add     $16, %rcx
522         movdqa  %xmm4, %xmm3
524         add     $16, %r10
525         jg      LABEL(nibble_ashr_3)    /* cross page boundary */
527         movdqa  (%rsi, %rcx), %xmm1
528         movdqa  (%rdi, %rcx), %xmm2
529         movdqa  %xmm2, %xmm4
531 #ifndef USE_SSSE3
532         psrldq  $3, %xmm3
533         pslldq  $13, %xmm2
534         por     %xmm3, %xmm2            /* merge into one 16byte value */
535 #else
536         palignr $3, %xmm3, %xmm2        /* merge into one 16byte value */
537 #endif
539         pcmpeqb %xmm1, %xmm0
540         pcmpeqb %xmm2, %xmm1
541         psubb   %xmm0, %xmm1
542         pmovmskb %xmm1, %edx
543         sub     $0xffff, %edx
544         jnz     LABEL(exit)
546 #ifdef USE_AS_STRNCMP
547         sub     $16, %r11
548         jbe     LABEL(strcmp_exitz)
549 #endif
551         add     $16, %rcx
552         movdqa  %xmm4, %xmm3
553         jmp     LABEL(loop_ashr_3)
555         .p2align 4
556 LABEL(nibble_ashr_3):
557         pcmpeqb %xmm3, %xmm0            /* check nibble for null char */
558         pmovmskb %xmm0, %edx
559         test    $0xfff8, %edx
560         jnz     LABEL(ashr_3_exittail)
562 #ifdef USE_AS_STRNCMP
563         cmp     $12, %r11
564         jbe     LABEL(ashr_3_exittail)
565 #endif
567         pxor    %xmm0, %xmm0
568         sub     $0x1000, %r10
569         jmp     LABEL(gobble_ashr_3)
571         .p2align 4
572 LABEL(ashr_3_exittail):
573         movdqa  (%rsi, %rcx), %xmm1
574         psrldq  $3, %xmm0
575         psrldq  $3, %xmm3
576         jmp     LABEL(aftertail)
579  * The following cases will be handled by ashr_4
580  *  rcx(offset of rsi)  rax(offset of rdi)  relative offset      corresponding case
581  *        n(12~15)            n -12         3(15 +(n-12) - n)         ashr_4
582  */
583         .p2align 4
584 LABEL(ashr_4):
585         pxor    %xmm0, %xmm0
586         movdqa  (%rdi), %xmm2
587         movdqa  (%rsi), %xmm1
588         pcmpeqb %xmm1, %xmm0
589         pslldq  $12, %xmm2
590         pcmpeqb %xmm1, %xmm2
591         psubb   %xmm0, %xmm2
592         pmovmskb %xmm2, %r9d
593         shr     %cl, %edx
594         shr     %cl, %r9d
595         sub     %r9d, %edx
596         jnz     LABEL(less32bytes)
597         movdqa  (%rdi), %xmm3
599         UPDATE_STRNCMP_COUNTER
601         pxor    %xmm0, %xmm0
602         mov     $16, %rcx       /* index for loads */
603         mov     $4, %r9d        /* byte position left over from less32bytes case */
604         /*
605          * Setup %r10 value allows us to detect crossing a page boundary.
606          * When %r10 goes positive we have crossed a page boundary and
607          * need to do a nibble.
608          */
609         lea     4(%rdi), %r10
610         and     $0xfff, %r10    /* offset into 4K page */
611         sub     $0x1000, %r10   /* subtract 4K pagesize */
613         .p2align 4
614 LABEL(loop_ashr_4):
615         add     $16, %r10
616         jg      LABEL(nibble_ashr_4)
618 LABEL(gobble_ashr_4):
619         movdqa  (%rsi, %rcx), %xmm1
620         movdqa  (%rdi, %rcx), %xmm2
621         movdqa  %xmm2, %xmm4
623 #ifndef USE_SSSE3
624         psrldq  $4, %xmm3
625         pslldq  $12, %xmm2
626         por     %xmm3, %xmm2            /* merge into one 16byte value */
627 #else
628         palignr $4, %xmm3, %xmm2        /* merge into one 16byte value */
629 #endif
631         pcmpeqb %xmm1, %xmm0
632         pcmpeqb %xmm2, %xmm1
633         psubb   %xmm0, %xmm1
634         pmovmskb %xmm1, %edx
635         sub     $0xffff, %edx
636         jnz     LABEL(exit)
638 #ifdef USE_AS_STRNCMP
639         sub     $16, %r11
640         jbe     LABEL(strcmp_exitz)
641 #endif
643         add     $16, %rcx
644         movdqa  %xmm4, %xmm3
646         add     $16, %r10
647         jg      LABEL(nibble_ashr_4)    /* cross page boundary */
649         movdqa  (%rsi, %rcx), %xmm1
650         movdqa  (%rdi, %rcx), %xmm2
651         movdqa  %xmm2, %xmm4
653 #ifndef USE_SSSE3
654         psrldq  $4, %xmm3
655         pslldq  $12, %xmm2
656         por     %xmm3, %xmm2            /* merge into one 16byte value */
657 #else
658         palignr $4, %xmm3, %xmm2        /* merge into one 16byte value */
659 #endif
661         pcmpeqb %xmm1, %xmm0
662         pcmpeqb %xmm2, %xmm1
663         psubb   %xmm0, %xmm1
664         pmovmskb %xmm1, %edx
665         sub     $0xffff, %edx
666         jnz     LABEL(exit)
668 #ifdef USE_AS_STRNCMP
669         sub     $16, %r11
670         jbe     LABEL(strcmp_exitz)
671 #endif
673         add     $16, %rcx
674         movdqa  %xmm4, %xmm3
675         jmp     LABEL(loop_ashr_4)
677         .p2align 4
678 LABEL(nibble_ashr_4):
679         pcmpeqb %xmm3, %xmm0            /* check nibble for null char */
680         pmovmskb %xmm0, %edx
681         test    $0xfff0, %edx
682         jnz     LABEL(ashr_4_exittail)
684 #ifdef USE_AS_STRNCMP
685         cmp     $11, %r11
686         jbe     LABEL(ashr_4_exittail)
687 #endif
689         pxor    %xmm0, %xmm0
690         sub     $0x1000, %r10
691         jmp     LABEL(gobble_ashr_4)
693         .p2align 4
694 LABEL(ashr_4_exittail):
695         movdqa  (%rsi, %rcx), %xmm1
696         psrldq  $4, %xmm0
697         psrldq  $4, %xmm3
698         jmp     LABEL(aftertail)
701  * The following cases will be handled by ashr_5
702  *  rcx(offset of rsi)  rax(offset of rdi)        relative offset      corresponding case
703  *        n(11~15)          n - 11                4(15 +(n-11) - n)         ashr_5
704  */
705         .p2align 4
706 LABEL(ashr_5):
707         pxor    %xmm0, %xmm0
708         movdqa  (%rdi), %xmm2
709         movdqa  (%rsi), %xmm1
710         pcmpeqb %xmm1, %xmm0
711         pslldq  $11, %xmm2
712         pcmpeqb %xmm1, %xmm2
713         psubb   %xmm0, %xmm2
714         pmovmskb %xmm2, %r9d
715         shr     %cl, %edx
716         shr     %cl, %r9d
717         sub     %r9d, %edx
718         jnz     LABEL(less32bytes)
719         movdqa  (%rdi), %xmm3
721         UPDATE_STRNCMP_COUNTER
723         pxor    %xmm0, %xmm0
724         mov     $16, %rcx       /* index for loads */
725         mov     $5, %r9d        /* byte position left over from less32bytes case */
726         /*
727          * Setup %r10 value allows us to detect crossing a page boundary.
728          * When %r10 goes positive we have crossed a page boundary and
729          * need to do a nibble.
730          */
731         lea     5(%rdi), %r10
732         and     $0xfff, %r10    /* offset into 4K page */
733         sub     $0x1000, %r10   /* subtract 4K pagesize */
735         .p2align 4
736 LABEL(loop_ashr_5):
737         add     $16, %r10
738         jg      LABEL(nibble_ashr_5)
740 LABEL(gobble_ashr_5):
741         movdqa  (%rsi, %rcx), %xmm1
742         movdqa  (%rdi, %rcx), %xmm2
743         movdqa  %xmm2, %xmm4
745 #ifndef USE_SSSE3
746         psrldq  $5, %xmm3
747         pslldq  $11, %xmm2
748         por     %xmm3, %xmm2            /* merge into one 16byte value */
749 #else
750         palignr $5, %xmm3, %xmm2        /* merge into one 16byte value */
751 #endif
753         pcmpeqb %xmm1, %xmm0
754         pcmpeqb %xmm2, %xmm1
755         psubb   %xmm0, %xmm1
756         pmovmskb %xmm1, %edx
757         sub     $0xffff, %edx
758         jnz     LABEL(exit)
760 #ifdef USE_AS_STRNCMP
761         sub     $16, %r11
762         jbe     LABEL(strcmp_exitz)
763 #endif
765         add     $16, %rcx
766         movdqa  %xmm4, %xmm3
768         add     $16, %r10
769         jg      LABEL(nibble_ashr_5)    /* cross page boundary */
771         movdqa  (%rsi, %rcx), %xmm1
772         movdqa  (%rdi, %rcx), %xmm2
773         movdqa  %xmm2, %xmm4
775 #ifndef USE_SSSE3
776         psrldq  $5, %xmm3
777         pslldq  $11, %xmm2
778         por     %xmm3, %xmm2            /* merge into one 16byte value */
779 #else
780         palignr $5, %xmm3, %xmm2        /* merge into one 16byte value */
781 #endif
783         pcmpeqb %xmm1, %xmm0
784         pcmpeqb %xmm2, %xmm1
785         psubb   %xmm0, %xmm1
786         pmovmskb %xmm1, %edx
787         sub     $0xffff, %edx
788         jnz     LABEL(exit)
790 #ifdef USE_AS_STRNCMP
791         sub     $16, %r11
792         jbe     LABEL(strcmp_exitz)
793 #endif
795         add     $16, %rcx
796         movdqa  %xmm4, %xmm3
797         jmp     LABEL(loop_ashr_5)
799         .p2align 4
800 LABEL(nibble_ashr_5):
801         pcmpeqb %xmm3, %xmm0            /* check nibble for null char */
802         pmovmskb %xmm0, %edx
803         test    $0xffe0, %edx
804         jnz     LABEL(ashr_5_exittail)
806 #ifdef USE_AS_STRNCMP
807         cmp     $10, %r11
808         jbe     LABEL(ashr_5_exittail)
809 #endif
811         pxor    %xmm0, %xmm0
812         sub     $0x1000, %r10
813         jmp     LABEL(gobble_ashr_5)
815         .p2align 4
816 LABEL(ashr_5_exittail):
817         movdqa  (%rsi, %rcx), %xmm1
818         psrldq  $5, %xmm0
819         psrldq  $5, %xmm3
820         jmp     LABEL(aftertail)
823  * The following cases will be handled by ashr_6
824  *  rcx(offset of rsi)  rax(offset of rdi)        relative offset      corresponding case
825  *        n(10~15)          n - 10                5(15 +(n-10) - n)         ashr_6
826  */
827         .p2align 4
828 LABEL(ashr_6):
829         pxor    %xmm0, %xmm0
830         movdqa  (%rdi), %xmm2
831         movdqa  (%rsi), %xmm1
832         pcmpeqb %xmm1, %xmm0
833         pslldq  $10, %xmm2
834         pcmpeqb %xmm1, %xmm2
835         psubb   %xmm0, %xmm2
836         pmovmskb %xmm2, %r9d
837         shr     %cl, %edx
838         shr     %cl, %r9d
839         sub     %r9d, %edx
840         jnz     LABEL(less32bytes)
841         movdqa  (%rdi), %xmm3
843         UPDATE_STRNCMP_COUNTER
845         pxor    %xmm0, %xmm0
846         mov     $16, %rcx       /* index for loads */
847         mov     $6, %r9d        /* byte position left over from less32bytes case */
848         /*
849          * Setup %r10 value allows us to detect crossing a page boundary.
850          * When %r10 goes positive we have crossed a page boundary and
851          * need to do a nibble.
852          */
853         lea     6(%rdi), %r10
854         and     $0xfff, %r10    /* offset into 4K page */
855         sub     $0x1000, %r10   /* subtract 4K pagesize */
857         .p2align 4
858 LABEL(loop_ashr_6):
859         add     $16, %r10
860         jg      LABEL(nibble_ashr_6)
862 LABEL(gobble_ashr_6):
863         movdqa  (%rsi, %rcx), %xmm1
864         movdqa  (%rdi, %rcx), %xmm2
865         movdqa  %xmm2, %xmm4
867 #ifndef USE_SSSE3
868         psrldq  $6, %xmm3
869         pslldq  $10, %xmm2
870         por     %xmm3, %xmm2            /* merge into one 16byte value */
871 #else
872         palignr $6, %xmm3, %xmm2        /* merge into one 16byte value */
873 #endif
875         pcmpeqb %xmm1, %xmm0
876         pcmpeqb %xmm2, %xmm1
877         psubb   %xmm0, %xmm1
878         pmovmskb %xmm1, %edx
879         sub     $0xffff, %edx
880         jnz     LABEL(exit)
882 #ifdef USE_AS_STRNCMP
883         sub     $16, %r11
884         jbe     LABEL(strcmp_exitz)
885 #endif
887         add     $16, %rcx
888         movdqa  %xmm4, %xmm3
890         add     $16, %r10
891         jg      LABEL(nibble_ashr_6)    /* cross page boundary */
893         movdqa  (%rsi, %rcx), %xmm1
894         movdqa  (%rdi, %rcx), %xmm2
895         movdqa  %xmm2, %xmm4
897 #ifndef USE_SSSE3
898         psrldq  $6, %xmm3
899         pslldq  $10, %xmm2
900         por     %xmm3, %xmm2            /* merge into one 16byte value */
901 #else
902         palignr $6, %xmm3, %xmm2        /* merge into one 16byte value */
903 #endif
905         pcmpeqb %xmm1, %xmm0
906         pcmpeqb %xmm2, %xmm1
907         psubb   %xmm0, %xmm1
908         pmovmskb %xmm1, %edx
909         sub     $0xffff, %edx
910         jnz     LABEL(exit)
912 #ifdef USE_AS_STRNCMP
913         sub     $16, %r11
914         jbe     LABEL(strcmp_exitz)
915 #endif
917         add     $16, %rcx
918         movdqa  %xmm4, %xmm3
919         jmp     LABEL(loop_ashr_6)
921         .p2align 4
922 LABEL(nibble_ashr_6):
923         pcmpeqb %xmm3, %xmm0            /* check nibble for null char */
924         pmovmskb %xmm0, %edx
925         test    $0xffc0, %edx
926         jnz     LABEL(ashr_6_exittail)
928 #ifdef USE_AS_STRNCMP
929         cmp     $9, %r11
930         jbe     LABEL(ashr_6_exittail)
931 #endif
933         pxor    %xmm0, %xmm0
934         sub     $0x1000, %r10
935         jmp     LABEL(gobble_ashr_6)
937         .p2align 4
938 LABEL(ashr_6_exittail):
939         movdqa  (%rsi, %rcx), %xmm1
940         psrldq  $6, %xmm0
941         psrldq  $6, %xmm3
942         jmp     LABEL(aftertail)
945  * The following cases will be handled by ashr_7
946  *  rcx(offset of rsi)  rax(offset of rdi)        relative offset      corresponding case
947  *        n(9~15)          n - 9                6(15 +(n - 9) - n)         ashr_7
948  */
949         .p2align 4
950 LABEL(ashr_7):
951         pxor    %xmm0, %xmm0
952         movdqa  (%rdi), %xmm2
953         movdqa  (%rsi), %xmm1
954         pcmpeqb %xmm1, %xmm0
955         pslldq  $9, %xmm2
956         pcmpeqb %xmm1, %xmm2
957         psubb   %xmm0, %xmm2
958         pmovmskb %xmm2, %r9d
959         shr     %cl, %edx
960         shr     %cl, %r9d
961         sub     %r9d, %edx
962         jnz     LABEL(less32bytes)
963         movdqa  (%rdi), %xmm3
965         UPDATE_STRNCMP_COUNTER
967         pxor    %xmm0, %xmm0
968         mov     $16, %rcx       /* index for loads */
969         mov     $7, %r9d        /* byte position left over from less32bytes case */
970         /*
971          * Setup %r10 value allows us to detect crossing a page boundary.
972          * When %r10 goes positive we have crossed a page boundary and
973          * need to do a nibble.
974          */
975         lea     7(%rdi), %r10
976         and     $0xfff, %r10    /* offset into 4K page */
977         sub     $0x1000, %r10   /* subtract 4K pagesize */
979         .p2align 4
980 LABEL(loop_ashr_7):
981         add     $16, %r10
982         jg      LABEL(nibble_ashr_7)
984 LABEL(gobble_ashr_7):
985         movdqa  (%rsi, %rcx), %xmm1
986         movdqa  (%rdi, %rcx), %xmm2
987         movdqa  %xmm2, %xmm4
989 #ifndef USE_SSSE3
990         psrldq  $7, %xmm3
991         pslldq  $9, %xmm2
992         por     %xmm3, %xmm2            /* merge into one 16byte value */
993 #else
994         palignr $7, %xmm3, %xmm2        /* merge into one 16byte value */
995 #endif
997         pcmpeqb %xmm1, %xmm0
998         pcmpeqb %xmm2, %xmm1
999         psubb   %xmm0, %xmm1
1000         pmovmskb %xmm1, %edx
1001         sub     $0xffff, %edx
1002         jnz     LABEL(exit)
1004 #ifdef USE_AS_STRNCMP
1005         sub     $16, %r11
1006         jbe     LABEL(strcmp_exitz)
1007 #endif
1009         add     $16, %rcx
1010         movdqa  %xmm4, %xmm3
1012         add     $16, %r10
1013         jg      LABEL(nibble_ashr_7)    /* cross page boundary */
1015         movdqa  (%rsi, %rcx), %xmm1
1016         movdqa  (%rdi, %rcx), %xmm2
1017         movdqa  %xmm2, %xmm4
1019 #ifndef USE_SSSE3
1020         psrldq  $7, %xmm3
1021         pslldq  $9, %xmm2
1022         por     %xmm3, %xmm2            /* merge into one 16byte value */
1023 #else
1024         palignr $7, %xmm3, %xmm2        /* merge into one 16byte value */
1025 #endif
1027         pcmpeqb %xmm1, %xmm0
1028         pcmpeqb %xmm2, %xmm1
1029         psubb   %xmm0, %xmm1
1030         pmovmskb %xmm1, %edx
1031         sub     $0xffff, %edx
1032         jnz     LABEL(exit)
1034 #ifdef USE_AS_STRNCMP
1035         sub     $16, %r11
1036         jbe     LABEL(strcmp_exitz)
1037 #endif
1039         add     $16, %rcx
1040         movdqa  %xmm4, %xmm3
1041         jmp     LABEL(loop_ashr_7)
1043         .p2align 4
1044 LABEL(nibble_ashr_7):
1045         pcmpeqb %xmm3, %xmm0            /* check nibble for null char */
1046         pmovmskb %xmm0, %edx
1047         test    $0xff80, %edx
1048         jnz     LABEL(ashr_7_exittail)
1050 #ifdef USE_AS_STRNCMP
1051         cmp     $8, %r11
1052         jbe     LABEL(ashr_7_exittail)
1053 #endif
1055         pxor    %xmm0, %xmm0
1056         sub     $0x1000, %r10
1057         jmp     LABEL(gobble_ashr_7)
1059         .p2align 4
1060 LABEL(ashr_7_exittail):
1061         movdqa  (%rsi, %rcx), %xmm1
1062         psrldq  $7, %xmm0
1063         psrldq  $7, %xmm3
1064         jmp     LABEL(aftertail)
1067  *  The following cases will be handled by ashr_8
1068  *  rcx(offset of rsi)  rax(offset of rdi)        relative offset        corresponding case
1069  *        n(8~15)          n - 8                7(15 +(n - 8) - n)         ashr_8
1070  */
1071         .p2align 4
1072 LABEL(ashr_8):
1073         pxor    %xmm0, %xmm0
1074         movdqa  (%rdi), %xmm2
1075         movdqa  (%rsi), %xmm1
1076         pcmpeqb %xmm1, %xmm0
1077         pslldq  $8, %xmm2
1078         pcmpeqb %xmm1, %xmm2
1079         psubb   %xmm0, %xmm2
1080         pmovmskb %xmm2, %r9d
1081         shr     %cl, %edx
1082         shr     %cl, %r9d
1083         sub     %r9d, %edx
1084         jnz     LABEL(less32bytes)
1085         movdqa  (%rdi), %xmm3
1087         UPDATE_STRNCMP_COUNTER
1089         pxor    %xmm0, %xmm0
1090         mov     $16, %rcx       /* index for loads */
1091         mov     $8, %r9d        /* byte position left over from less32bytes case */
1092         /*
1093          * Setup %r10 value allows us to detect crossing a page boundary.
1094          * When %r10 goes positive we have crossed a page boundary and
1095          * need to do a nibble.
1096          */
1097         lea     8(%rdi), %r10
1098         and     $0xfff, %r10    /* offset into 4K page */
1099         sub     $0x1000, %r10   /* subtract 4K pagesize */
1101         .p2align 4
1102 LABEL(loop_ashr_8):
1103         add     $16, %r10
1104         jg      LABEL(nibble_ashr_8)
1106 LABEL(gobble_ashr_8):
1107         movdqa  (%rsi, %rcx), %xmm1
1108         movdqa  (%rdi, %rcx), %xmm2
1109         movdqa  %xmm2, %xmm4
1111 #ifndef USE_SSSE3
1112         psrldq  $8, %xmm3
1113         pslldq  $8, %xmm2
1114         por     %xmm3, %xmm2            /* merge into one 16byte value */
1115 #else
1116         palignr $8, %xmm3, %xmm2        /* merge into one 16byte value */
1117 #endif
1119         pcmpeqb %xmm1, %xmm0
1120         pcmpeqb %xmm2, %xmm1
1121         psubb   %xmm0, %xmm1
1122         pmovmskb %xmm1, %edx
1123         sub     $0xffff, %edx
1124         jnz     LABEL(exit)
1126 #ifdef USE_AS_STRNCMP
1127         sub     $16, %r11
1128         jbe     LABEL(strcmp_exitz)
1129 #endif
1131         add     $16, %rcx
1132         movdqa  %xmm4, %xmm3
1134         add     $16, %r10
1135         jg      LABEL(nibble_ashr_8)    /* cross page boundary */
1137         movdqa  (%rsi, %rcx), %xmm1
1138         movdqa  (%rdi, %rcx), %xmm2
1139         movdqa  %xmm2, %xmm4
1141 #ifndef USE_SSSE3
1142         psrldq  $8, %xmm3
1143         pslldq  $8, %xmm2
1144         por     %xmm3, %xmm2            /* merge into one 16byte value */
1145 #else
1146         palignr $8, %xmm3, %xmm2        /* merge into one 16byte value */
1147 #endif
1149         pcmpeqb %xmm1, %xmm0
1150         pcmpeqb %xmm2, %xmm1
1151         psubb   %xmm0, %xmm1
1152         pmovmskb %xmm1, %edx
1153         sub     $0xffff, %edx
1154         jnz     LABEL(exit)
1156 #ifdef USE_AS_STRNCMP
1157         sub     $16, %r11
1158         jbe     LABEL(strcmp_exitz)
1159 #endif
1161         add     $16, %rcx
1162         movdqa  %xmm4, %xmm3
1163         jmp     LABEL(loop_ashr_8)
1165         .p2align 4
1166 LABEL(nibble_ashr_8):
1167         pcmpeqb %xmm3, %xmm0            /* check nibble for null char */
1168         pmovmskb %xmm0, %edx
1169         test    $0xff00, %edx
1170         jnz     LABEL(ashr_8_exittail)
1172 #ifdef USE_AS_STRNCMP
1173         cmp     $7, %r11
1174         jbe     LABEL(ashr_8_exittail)
1175 #endif
1177         pxor    %xmm0, %xmm0
1178         sub     $0x1000, %r10
1179         jmp     LABEL(gobble_ashr_8)
1181         .p2align 4
1182 LABEL(ashr_8_exittail):
1183         movdqa  (%rsi, %rcx), %xmm1
1184         psrldq  $8, %xmm0
1185         psrldq  $8, %xmm3
1186         jmp     LABEL(aftertail)
1189  *  The following cases will be handled by ashr_9
1190  *  rcx(offset of rsi)  rax(offset of rdi)        relative offset        corresponding case
1191  *        n(7~15)          n - 7                8(15 +(n - 7) - n)         ashr_9
1192  */
1193         .p2align 4
1194 LABEL(ashr_9):
1195         pxor    %xmm0, %xmm0
1196         movdqa  (%rdi), %xmm2
1197         movdqa  (%rsi), %xmm1
1198         pcmpeqb %xmm1, %xmm0
1199         pslldq  $7, %xmm2
1200         pcmpeqb %xmm1, %xmm2
1201         psubb   %xmm0, %xmm2
1202         pmovmskb %xmm2, %r9d
1203         shr     %cl, %edx
1204         shr     %cl, %r9d
1205         sub     %r9d, %edx
1206         jnz     LABEL(less32bytes)
1207         movdqa  (%rdi), %xmm3
1209         UPDATE_STRNCMP_COUNTER
1211         pxor    %xmm0, %xmm0
1212         mov     $16, %rcx       /* index for loads */
1213         mov     $9, %r9d        /* byte position left over from less32bytes case */
1214         /*
1215          * Setup %r10 value allows us to detect crossing a page boundary.
1216          * When %r10 goes positive we have crossed a page boundary and
1217          * need to do a nibble.
1218          */
1219         lea     9(%rdi), %r10
1220         and     $0xfff, %r10    /* offset into 4K page */
1221         sub     $0x1000, %r10   /* subtract 4K pagesize */
1223         .p2align 4
1224 LABEL(loop_ashr_9):
1225         add     $16, %r10
1226         jg      LABEL(nibble_ashr_9)
1228 LABEL(gobble_ashr_9):
1229         movdqa  (%rsi, %rcx), %xmm1
1230         movdqa  (%rdi, %rcx), %xmm2
1231         movdqa  %xmm2, %xmm4
1233 #ifndef USE_SSSE3
1234         psrldq  $9, %xmm3
1235         pslldq  $7, %xmm2
1236         por     %xmm3, %xmm2            /* merge into one 16byte value */
1237 #else
1238         palignr $9, %xmm3, %xmm2        /* merge into one 16byte value */
1239 #endif
1241         pcmpeqb %xmm1, %xmm0
1242         pcmpeqb %xmm2, %xmm1
1243         psubb   %xmm0, %xmm1
1244         pmovmskb %xmm1, %edx
1245         sub     $0xffff, %edx
1246         jnz     LABEL(exit)
1248 #ifdef USE_AS_STRNCMP
1249         sub     $16, %r11
1250         jbe     LABEL(strcmp_exitz)
1251 #endif
1253         add     $16, %rcx
1254         movdqa  %xmm4, %xmm3
1256         add     $16, %r10
1257         jg      LABEL(nibble_ashr_9)    /* cross page boundary */
1259         movdqa  (%rsi, %rcx), %xmm1
1260         movdqa  (%rdi, %rcx), %xmm2
1261         movdqa  %xmm2, %xmm4
1263 #ifndef USE_SSSE3
1264         psrldq  $9, %xmm3
1265         pslldq  $7, %xmm2
1266         por     %xmm3, %xmm2            /* merge into one 16byte value */
1267 #else
1268         palignr $9, %xmm3, %xmm2        /* merge into one 16byte value */
1269 #endif
1271         pcmpeqb %xmm1, %xmm0
1272         pcmpeqb %xmm2, %xmm1
1273         psubb   %xmm0, %xmm1
1274         pmovmskb %xmm1, %edx
1275         sub     $0xffff, %edx
1276         jnz     LABEL(exit)
1278 #ifdef USE_AS_STRNCMP
1279         sub     $16, %r11
1280         jbe     LABEL(strcmp_exitz)
1281 #endif
1283         add     $16, %rcx
1284         movdqa  %xmm4, %xmm3            /* store for next cycle */
1285         jmp     LABEL(loop_ashr_9)
1287         .p2align 4
1288 LABEL(nibble_ashr_9):
1289         pcmpeqb %xmm3, %xmm0            /* check nibble for null char */
1290         pmovmskb %xmm0, %edx
1291         test    $0xfe00, %edx
1292         jnz     LABEL(ashr_9_exittail)
1294 #ifdef USE_AS_STRNCMP
1295         cmp     $6, %r11
1296         jbe     LABEL(ashr_9_exittail)
1297 #endif
1299         pxor    %xmm0, %xmm0
1300         sub     $0x1000, %r10
1301         jmp     LABEL(gobble_ashr_9)
1303         .p2align 4
1304 LABEL(ashr_9_exittail):
1305         movdqa  (%rsi, %rcx), %xmm1
1306         psrldq  $9, %xmm0
1307         psrldq  $9, %xmm3
1308         jmp     LABEL(aftertail)
1311  *  The following cases will be handled by ashr_10
1312  *  rcx(offset of rsi)  rax(offset of rdi)        relative offset        corresponding case
1313  *        n(6~15)          n - 6                9(15 +(n - 6) - n)         ashr_10
1314  */
1315         .p2align 4
1316 LABEL(ashr_10):
1317         pxor    %xmm0, %xmm0
1318         movdqa  (%rdi), %xmm2
1319         movdqa  (%rsi), %xmm1
1320         pcmpeqb %xmm1, %xmm0
1321         pslldq  $6, %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     $10, %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     10(%rdi), %r10
1342         and     $0xfff, %r10    /* offset into 4K page */
1343         sub     $0x1000, %r10   /* subtract 4K pagesize */
1345         .p2align 4
1346 LABEL(loop_ashr_10):
1347         add     $16, %r10
1348         jg      LABEL(nibble_ashr_10)
1350 LABEL(gobble_ashr_10):
1351         movdqa  (%rsi, %rcx), %xmm1
1352         movdqa  (%rdi, %rcx), %xmm2
1353         movdqa  %xmm2, %xmm4
1355 #ifndef USE_SSSE3
1356         psrldq  $10, %xmm3
1357         pslldq  $6, %xmm2
1358         por     %xmm3, %xmm2            /* merge into one 16byte value */
1359 #else
1360         palignr $10, %xmm3, %xmm2       /* merge into one 16byte value */
1361 #endif
1363         pcmpeqb %xmm1, %xmm0
1364         pcmpeqb %xmm2, %xmm1
1365         psubb   %xmm0, %xmm1
1366         pmovmskb %xmm1, %edx
1367         sub     $0xffff, %edx
1368         jnz     LABEL(exit)
1370 #ifdef USE_AS_STRNCMP
1371         sub     $16, %r11
1372         jbe     LABEL(strcmp_exitz)
1373 #endif
1375         add     $16, %rcx
1376         movdqa  %xmm4, %xmm3
1378         add     $16, %r10
1379         jg      LABEL(nibble_ashr_10)   /* cross page boundary */
1381         movdqa  (%rsi, %rcx), %xmm1
1382         movdqa  (%rdi, %rcx), %xmm2
1383         movdqa  %xmm2, %xmm4
1385 #ifndef USE_SSSE3
1386         psrldq  $10, %xmm3
1387         pslldq  $6, %xmm2
1388         por     %xmm3, %xmm2            /* merge into one 16byte value */
1389 #else
1390         palignr $10, %xmm3, %xmm2       /* merge into one 16byte value */
1391 #endif
1393         pcmpeqb %xmm1, %xmm0
1394         pcmpeqb %xmm2, %xmm1
1395         psubb   %xmm0, %xmm1
1396         pmovmskb %xmm1, %edx
1397         sub     $0xffff, %edx
1398         jnz     LABEL(exit)
1400 #ifdef USE_AS_STRNCMP
1401         sub     $16, %r11
1402         jbe     LABEL(strcmp_exitz)
1403 #endif
1405         add     $16, %rcx
1406         movdqa  %xmm4, %xmm3
1407         jmp     LABEL(loop_ashr_10)
1409         .p2align 4
1410 LABEL(nibble_ashr_10):
1411         pcmpeqb %xmm3, %xmm0            /* check nibble for null char */
1412         pmovmskb %xmm0, %edx
1413         test    $0xfc00, %edx
1414         jnz     LABEL(ashr_10_exittail)
1416 #ifdef USE_AS_STRNCMP
1417         cmp     $5, %r11
1418         jbe     LABEL(ashr_10_exittail)
1419 #endif
1421         pxor    %xmm0, %xmm0
1422         sub     $0x1000, %r10
1423         jmp     LABEL(gobble_ashr_10)
1425         .p2align 4
1426 LABEL(ashr_10_exittail):
1427         movdqa  (%rsi, %rcx), %xmm1
1428         psrldq  $10, %xmm0
1429         psrldq  $10, %xmm3
1430         jmp     LABEL(aftertail)
1433  *  The following cases will be handled by ashr_11
1434  *  rcx(offset of rsi)  rax(offset of rdi)        relative offset        corresponding case
1435  *        n(5~15)          n - 5                10(15 +(n - 5) - n)         ashr_11
1436  */
1437         .p2align 4
1438 LABEL(ashr_11):
1439         pxor    %xmm0, %xmm0
1440         movdqa  (%rdi), %xmm2
1441         movdqa  (%rsi), %xmm1
1442         pcmpeqb %xmm1, %xmm0
1443         pslldq  $5, %xmm2
1444         pcmpeqb %xmm1, %xmm2
1445         psubb   %xmm0, %xmm2
1446         pmovmskb %xmm2, %r9d
1447         shr     %cl, %edx
1448         shr     %cl, %r9d
1449         sub     %r9d, %edx
1450         jnz     LABEL(less32bytes)
1451         movdqa  (%rdi), %xmm3
1453         UPDATE_STRNCMP_COUNTER
1455         pxor    %xmm0, %xmm0
1456         mov     $16, %rcx       /* index for loads */
1457         mov     $11, %r9d       /* byte position left over from less32bytes case */
1458         /*
1459          * Setup %r10 value allows us to detect crossing a page boundary.
1460          * When %r10 goes positive we have crossed a page boundary and
1461          * need to do a nibble.
1462          */
1463         lea     11(%rdi), %r10
1464         and     $0xfff, %r10    /* offset into 4K page */
1465         sub     $0x1000, %r10   /* subtract 4K pagesize */
1467         .p2align 4
1468 LABEL(loop_ashr_11):
1469         add     $16, %r10
1470         jg      LABEL(nibble_ashr_11)
1472 LABEL(gobble_ashr_11):
1473         movdqa  (%rsi, %rcx), %xmm1
1474         movdqa  (%rdi, %rcx), %xmm2
1475         movdqa  %xmm2, %xmm4
1477 #ifndef USE_SSSE3
1478         psrldq  $11, %xmm3
1479         pslldq  $5, %xmm2
1480         por     %xmm3, %xmm2            /* merge into one 16byte value */
1481 #else
1482         palignr $11, %xmm3, %xmm2       /* merge into one 16byte value */
1483 #endif
1485         pcmpeqb %xmm1, %xmm0
1486         pcmpeqb %xmm2, %xmm1
1487         psubb   %xmm0, %xmm1
1488         pmovmskb %xmm1, %edx
1489         sub     $0xffff, %edx
1490         jnz     LABEL(exit)
1492 #ifdef USE_AS_STRNCMP
1493         sub     $16, %r11
1494         jbe     LABEL(strcmp_exitz)
1495 #endif
1497         add     $16, %rcx
1498         movdqa  %xmm4, %xmm3
1500         add     $16, %r10
1501         jg      LABEL(nibble_ashr_11)   /* cross page boundary */
1503         movdqa  (%rsi, %rcx), %xmm1
1504         movdqa  (%rdi, %rcx), %xmm2
1505         movdqa  %xmm2, %xmm4
1507 #ifndef USE_SSSE3
1508         psrldq  $11, %xmm3
1509         pslldq  $5, %xmm2
1510         por     %xmm3, %xmm2            /* merge into one 16byte value */
1511 #else
1512         palignr $11, %xmm3, %xmm2       /* merge into one 16byte value */
1513 #endif
1515         pcmpeqb %xmm1, %xmm0
1516         pcmpeqb %xmm2, %xmm1
1517         psubb   %xmm0, %xmm1
1518         pmovmskb %xmm1, %edx
1519         sub     $0xffff, %edx
1520         jnz     LABEL(exit)
1522 #ifdef USE_AS_STRNCMP
1523         sub     $16, %r11
1524         jbe     LABEL(strcmp_exitz)
1525 #endif
1527         add     $16, %rcx
1528         movdqa  %xmm4, %xmm3
1529         jmp     LABEL(loop_ashr_11)
1531         .p2align 4
1532 LABEL(nibble_ashr_11):
1533         pcmpeqb %xmm3, %xmm0            /* check nibble for null char */
1534         pmovmskb %xmm0, %edx
1535         test    $0xf800, %edx
1536         jnz     LABEL(ashr_11_exittail)
1538 #ifdef USE_AS_STRNCMP
1539         cmp     $4, %r11
1540         jbe     LABEL(ashr_11_exittail)
1541 #endif
1543         pxor    %xmm0, %xmm0
1544         sub     $0x1000, %r10
1545         jmp     LABEL(gobble_ashr_11)
1547         .p2align 4
1548 LABEL(ashr_11_exittail):
1549         movdqa  (%rsi, %rcx), %xmm1
1550         psrldq  $11, %xmm0
1551         psrldq  $11, %xmm3
1552         jmp     LABEL(aftertail)
1555  *  The following cases will be handled by ashr_12
1556  *  rcx(offset of rsi)  rax(offset of rdi)        relative offset        corresponding case
1557  *        n(4~15)          n - 4                11(15 +(n - 4) - n)         ashr_12
1558  */
1559         .p2align 4
1560 LABEL(ashr_12):
1561         pxor    %xmm0, %xmm0
1562         movdqa  (%rdi), %xmm2
1563         movdqa  (%rsi), %xmm1
1564         pcmpeqb %xmm1, %xmm0
1565         pslldq  $4, %xmm2
1566         pcmpeqb %xmm1, %xmm2
1567         psubb   %xmm0, %xmm2
1568         pmovmskb %xmm2, %r9d
1569         shr     %cl, %edx
1570         shr     %cl, %r9d
1571         sub     %r9d, %edx
1572         jnz     LABEL(less32bytes)
1573         movdqa  (%rdi), %xmm3
1575         UPDATE_STRNCMP_COUNTER
1577         pxor    %xmm0, %xmm0
1578         mov     $16, %rcx       /* index for loads */
1579         mov     $12, %r9d       /* byte position left over from less32bytes case */
1580         /*
1581          * Setup %r10 value allows us to detect crossing a page boundary.
1582          * When %r10 goes positive we have crossed a page boundary and
1583          * need to do a nibble.
1584          */
1585         lea     12(%rdi), %r10
1586         and     $0xfff, %r10    /* offset into 4K page */
1587         sub     $0x1000, %r10   /* subtract 4K pagesize */
1589         .p2align 4
1590 LABEL(loop_ashr_12):
1591         add     $16, %r10
1592         jg      LABEL(nibble_ashr_12)
1594 LABEL(gobble_ashr_12):
1595         movdqa  (%rsi, %rcx), %xmm1
1596         movdqa  (%rdi, %rcx), %xmm2
1597         movdqa  %xmm2, %xmm4
1599 #ifndef USE_SSSE3
1600         psrldq  $12, %xmm3
1601         pslldq  $4, %xmm2
1602         por     %xmm3, %xmm2            /* merge into one 16byte value */
1603 #else
1604         palignr $12, %xmm3, %xmm2       /* merge into one 16byte value */
1605 #endif
1607         pcmpeqb %xmm1, %xmm0
1608         pcmpeqb %xmm2, %xmm1
1609         psubb   %xmm0, %xmm1
1610         pmovmskb %xmm1, %edx
1611         sub     $0xffff, %edx
1612         jnz     LABEL(exit)
1614 #ifdef USE_AS_STRNCMP
1615         sub     $16, %r11
1616         jbe     LABEL(strcmp_exitz)
1617 #endif
1619         add     $16, %rcx
1620         movdqa  %xmm4, %xmm3
1622         add     $16, %r10
1623         jg      LABEL(nibble_ashr_12)   /* cross page boundary */
1625         movdqa  (%rsi, %rcx), %xmm1
1626         movdqa  (%rdi, %rcx), %xmm2
1627         movdqa  %xmm2, %xmm4
1629 #ifndef USE_SSSE3
1630         psrldq  $12, %xmm3
1631         pslldq  $4, %xmm2
1632         por     %xmm3, %xmm2            /* merge into one 16byte value */
1633 #else
1634         palignr $12, %xmm3, %xmm2       /* merge into one 16byte value */
1635 #endif
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_12)
1653         .p2align 4
1654 LABEL(nibble_ashr_12):
1655         pcmpeqb %xmm3, %xmm0            /* check nibble for null char */
1656         pmovmskb %xmm0, %edx
1657         test    $0xf000, %edx
1658         jnz     LABEL(ashr_12_exittail)
1660 #ifdef USE_AS_STRNCMP
1661         cmp     $3, %r11
1662         jbe     LABEL(ashr_12_exittail)
1663 #endif
1665         pxor    %xmm0, %xmm0
1666         sub     $0x1000, %r10
1667         jmp     LABEL(gobble_ashr_12)
1669         .p2align 4
1670 LABEL(ashr_12_exittail):
1671         movdqa  (%rsi, %rcx), %xmm1
1672         psrldq  $12, %xmm0
1673         psrldq  $12, %xmm3
1674         jmp     LABEL(aftertail)
1677  *  The following cases will be handled by ashr_13
1678  *  rcx(offset of rsi)  rax(offset of rdi)        relative offset        corresponding case
1679  *        n(3~15)          n - 3                12(15 +(n - 3) - n)         ashr_13
1680  */
1681         .p2align 4
1682 LABEL(ashr_13):
1683         pxor    %xmm0, %xmm0
1684         movdqa  (%rdi), %xmm2
1685         movdqa  (%rsi), %xmm1
1686         pcmpeqb %xmm1, %xmm0
1687         pslldq  $3, %xmm2
1688         pcmpeqb %xmm1, %xmm2
1689         psubb   %xmm0, %xmm2
1690         pmovmskb %xmm2, %r9d
1691         shr     %cl, %edx
1692         shr     %cl, %r9d
1693         sub     %r9d, %edx
1694         jnz     LABEL(less32bytes)
1695         movdqa  (%rdi), %xmm3
1697         UPDATE_STRNCMP_COUNTER
1699         pxor    %xmm0, %xmm0
1700         mov     $16, %rcx       /* index for loads */
1701         mov     $13, %r9d       /* byte position left over from less32bytes case */
1702         /*
1703          * Setup %r10 value allows us to detect crossing a page boundary.
1704          * When %r10 goes positive we have crossed a page boundary and
1705          * need to do a nibble.
1706          */
1707         lea     13(%rdi), %r10
1708         and     $0xfff, %r10    /* offset into 4K page */
1709         sub     $0x1000, %r10   /* subtract 4K pagesize */
1711         .p2align 4
1712 LABEL(loop_ashr_13):
1713         add     $16, %r10
1714         jg      LABEL(nibble_ashr_13)
1716 LABEL(gobble_ashr_13):
1717         movdqa  (%rsi, %rcx), %xmm1
1718         movdqa  (%rdi, %rcx), %xmm2
1719         movdqa  %xmm2, %xmm4
1721 #ifndef USE_SSSE3
1722         psrldq  $13, %xmm3
1723         pslldq  $3, %xmm2
1724         por     %xmm3, %xmm2            /* merge into one 16byte value */
1725 #else
1726         palignr $13, %xmm3, %xmm2       /* merge into one 16byte value */
1727 #endif
1729         pcmpeqb %xmm1, %xmm0
1730         pcmpeqb %xmm2, %xmm1
1731         psubb   %xmm0, %xmm1
1732         pmovmskb %xmm1, %edx
1733         sub     $0xffff, %edx
1734         jnz     LABEL(exit)
1736 #ifdef USE_AS_STRNCMP
1737         sub     $16, %r11
1738         jbe     LABEL(strcmp_exitz)
1739 #endif
1741         add     $16, %rcx
1742         movdqa  %xmm4, %xmm3
1744         add     $16, %r10
1745         jg      LABEL(nibble_ashr_13)   /* cross page boundary */
1747         movdqa  (%rsi, %rcx), %xmm1
1748         movdqa  (%rdi, %rcx), %xmm2
1749         movdqa  %xmm2, %xmm4
1751 #ifndef USE_SSSE3
1752         psrldq  $13, %xmm3
1753         pslldq  $3, %xmm2
1754         por     %xmm3, %xmm2            /* merge into one 16byte value */
1755 #else
1756         palignr $13, %xmm3, %xmm2       /* merge into one 16byte value */
1757 #endif
1759         pcmpeqb %xmm1, %xmm0
1760         pcmpeqb %xmm2, %xmm1
1761         psubb   %xmm0, %xmm1
1762         pmovmskb %xmm1, %edx
1763         sub     $0xffff, %edx
1764         jnz     LABEL(exit)
1766 #ifdef USE_AS_STRNCMP
1767         sub     $16, %r11
1768         jbe     LABEL(strcmp_exitz)
1769 #endif
1771         add     $16, %rcx
1772         movdqa  %xmm4, %xmm3
1773         jmp     LABEL(loop_ashr_13)
1775         .p2align 4
1776 LABEL(nibble_ashr_13):
1777         pcmpeqb %xmm3, %xmm0            /* check nibble for null char */
1778         pmovmskb %xmm0, %edx
1779         test    $0xe000, %edx
1780         jnz     LABEL(ashr_13_exittail)
1782 #ifdef USE_AS_STRNCMP
1783         cmp     $2, %r11
1784         jbe     LABEL(ashr_13_exittail)
1785 #endif
1787         pxor    %xmm0, %xmm0
1788         sub     $0x1000, %r10
1789         jmp     LABEL(gobble_ashr_13)
1791         .p2align 4
1792 LABEL(ashr_13_exittail):
1793         movdqa  (%rsi, %rcx), %xmm1
1794         psrldq  $13, %xmm0
1795         psrldq  $13, %xmm3
1796         jmp     LABEL(aftertail)
1799  *  The following cases will be handled by ashr_14
1800  *  rcx(offset of rsi)  rax(offset of rdi)        relative offset        corresponding case
1801  *        n(2~15)          n - 2                13(15 +(n - 2) - n)         ashr_14
1802  */
1803         .p2align 4
1804 LABEL(ashr_14):
1805         pxor    %xmm0, %xmm0
1806         movdqa  (%rdi), %xmm2
1807         movdqa  (%rsi), %xmm1
1808         pcmpeqb %xmm1, %xmm0
1809         pslldq  $2, %xmm2
1810         pcmpeqb %xmm1, %xmm2
1811         psubb   %xmm0, %xmm2
1812         pmovmskb %xmm2, %r9d
1813         shr     %cl, %edx
1814         shr     %cl, %r9d
1815         sub     %r9d, %edx
1816         jnz     LABEL(less32bytes)
1817         movdqa  (%rdi), %xmm3
1819         UPDATE_STRNCMP_COUNTER
1821         pxor    %xmm0, %xmm0
1822         mov     $16, %rcx       /* index for loads */
1823         mov     $14, %r9d       /* byte position left over from less32bytes case */
1824         /*
1825          * Setup %r10 value allows us to detect crossing a page boundary.
1826          * When %r10 goes positive we have crossed a page boundary and
1827          * need to do a nibble.
1828          */
1829         lea     14(%rdi), %r10
1830         and     $0xfff, %r10    /* offset into 4K page */
1831         sub     $0x1000, %r10   /* subtract 4K pagesize */
1833         .p2align 4
1834 LABEL(loop_ashr_14):
1835         add     $16, %r10
1836         jg      LABEL(nibble_ashr_14)
1838 LABEL(gobble_ashr_14):
1839         movdqa  (%rsi, %rcx), %xmm1
1840         movdqa  (%rdi, %rcx), %xmm2
1841         movdqa  %xmm2, %xmm4
1843 #ifndef USE_SSSE3
1844         psrldq  $14, %xmm3
1845         pslldq  $2, %xmm2
1846         por     %xmm3, %xmm2            /* merge into one 16byte value */
1847 #else
1848         palignr $14, %xmm3, %xmm2       /* merge into one 16byte value */
1849 #endif
1851         pcmpeqb %xmm1, %xmm0
1852         pcmpeqb %xmm2, %xmm1
1853         psubb   %xmm0, %xmm1
1854         pmovmskb %xmm1, %edx
1855         sub     $0xffff, %edx
1856         jnz     LABEL(exit)
1858 #ifdef USE_AS_STRNCMP
1859         sub     $16, %r11
1860         jbe     LABEL(strcmp_exitz)
1861 #endif
1863         add     $16, %rcx
1864         movdqa  %xmm4, %xmm3
1866         add     $16, %r10
1867         jg      LABEL(nibble_ashr_14)   /* cross page boundary */
1869         movdqa  (%rsi, %rcx), %xmm1
1870         movdqa  (%rdi, %rcx), %xmm2
1871         movdqa  %xmm2, %xmm4
1873 #ifndef USE_SSSE3
1874         psrldq  $14, %xmm3
1875         pslldq  $2, %xmm2
1876         por     %xmm3, %xmm2            /* merge into one 16byte value */
1877 #else
1878         palignr $14, %xmm3, %xmm2       /* merge into one 16byte value */
1879 #endif
1881         pcmpeqb %xmm1, %xmm0
1882         pcmpeqb %xmm2, %xmm1
1883         psubb   %xmm0, %xmm1
1884         pmovmskb %xmm1, %edx
1885         sub     $0xffff, %edx
1886         jnz     LABEL(exit)
1888 #ifdef USE_AS_STRNCMP
1889         sub     $16, %r11
1890         jbe     LABEL(strcmp_exitz)
1891 #endif
1893         add     $16, %rcx
1894         movdqa  %xmm4, %xmm3
1895         jmp     LABEL(loop_ashr_14)
1897         .p2align 4
1898 LABEL(nibble_ashr_14):
1899         pcmpeqb %xmm3, %xmm0            /* check nibble for null char */
1900         pmovmskb %xmm0, %edx
1901         test    $0xc000, %edx
1902         jnz     LABEL(ashr_14_exittail)
1904 #ifdef USE_AS_STRNCMP
1905         cmp     $1, %r11
1906         jbe     LABEL(ashr_14_exittail)
1907 #endif
1909         pxor    %xmm0, %xmm0
1910         sub     $0x1000, %r10
1911         jmp     LABEL(gobble_ashr_14)
1913         .p2align 4
1914 LABEL(ashr_14_exittail):
1915         movdqa  (%rsi, %rcx), %xmm1
1916         psrldq  $14, %xmm0
1917         psrldq  $14, %xmm3
1918         jmp     LABEL(aftertail)
1921  *  The following cases will be handled by ashr_15
1922  *  rcx(offset of rsi)  rax(offset of rdi)        relative offset        corresponding case
1923  *        n(1~15)          n - 1                14(15 +(n - 1) - n)         ashr_15
1924  */
1925         .p2align 4
1926 LABEL(ashr_15):
1927         pxor    %xmm0, %xmm0
1928         movdqa  (%rdi), %xmm2
1929         movdqa  (%rsi), %xmm1
1930         pcmpeqb %xmm1, %xmm0
1931         pslldq  $1, %xmm2
1932         pcmpeqb %xmm1, %xmm2
1933         psubb   %xmm0, %xmm2
1934         pmovmskb %xmm2, %r9d
1935         shr     %cl, %edx
1936         shr     %cl, %r9d
1937         sub     %r9d, %edx
1938         jnz     LABEL(less32bytes)
1940         movdqa  (%rdi), %xmm3
1942         UPDATE_STRNCMP_COUNTER
1944         pxor    %xmm0, %xmm0
1945         mov     $16, %rcx       /* index for loads */
1946         mov     $15, %r9d       /* byte position left over from less32bytes case */
1947         /*
1948          * Setup %r10 value allows us to detect crossing a page boundary.
1949          * When %r10 goes positive we have crossed a page boundary and
1950          * need to do a nibble.
1951          */
1952         lea     15(%rdi), %r10
1953         and     $0xfff, %r10    /* offset into 4K page */
1955         sub     $0x1000, %r10   /* subtract 4K pagesize */
1957         .p2align 4
1958 LABEL(loop_ashr_15):
1959         add     $16, %r10
1960         jg      LABEL(nibble_ashr_15)
1962 LABEL(gobble_ashr_15):
1963         movdqa  (%rsi, %rcx), %xmm1
1964         movdqa  (%rdi, %rcx), %xmm2
1965         movdqa  %xmm2, %xmm4
1967 #ifndef USE_SSSE3
1968         psrldq  $15, %xmm3
1969         pslldq  $1, %xmm2
1970         por     %xmm3, %xmm2            /* merge into one 16byte value */
1971 #else
1972         palignr $15, %xmm3, %xmm2       /* merge into one 16byte value */
1973 #endif
1975         pcmpeqb %xmm1, %xmm0
1976         pcmpeqb %xmm2, %xmm1
1977         psubb   %xmm0, %xmm1
1978         pmovmskb %xmm1, %edx
1979         sub     $0xffff, %edx
1980         jnz     LABEL(exit)
1982 #ifdef USE_AS_STRNCMP
1983         sub     $16, %r11
1984         jbe     LABEL(strcmp_exitz)
1985 #endif
1987         add     $16, %rcx
1988         movdqa  %xmm4, %xmm3
1990         add     $16, %r10
1991         jg      LABEL(nibble_ashr_15)   /* cross page boundary */
1993         movdqa  (%rsi, %rcx), %xmm1
1994         movdqa  (%rdi, %rcx), %xmm2
1995         movdqa  %xmm2, %xmm4
1997 #ifndef USE_SSSE3
1998         psrldq  $15, %xmm3
1999         pslldq  $1, %xmm2
2000         por     %xmm3, %xmm2            /* merge into one 16byte value */
2001 #else
2002         palignr $15, %xmm3, %xmm2       /* merge into one 16byte value */
2003 #endif
2005         pcmpeqb %xmm1, %xmm0
2006         pcmpeqb %xmm2, %xmm1
2007         psubb   %xmm0, %xmm1
2008         pmovmskb %xmm1, %edx
2009         sub     $0xffff, %edx
2010         jnz     LABEL(exit)
2012 #ifdef USE_AS_STRNCMP
2013         sub     $16, %r11
2014         jbe     LABEL(strcmp_exitz)
2015 #endif
2017         add     $16, %rcx
2018         movdqa  %xmm4, %xmm3
2019         jmp     LABEL(loop_ashr_15)
2021         .p2align 4
2022 LABEL(nibble_ashr_15):
2023         pcmpeqb %xmm3, %xmm0            /* check nibble for null char */
2024         pmovmskb %xmm0, %edx
2025         test    $0x8000, %edx
2026         jnz     LABEL(ashr_15_exittail)
2028 #ifdef USE_AS_STRNCMP
2029         test    %r11, %r11
2030         je      LABEL(ashr_15_exittail)
2031 #endif
2033         pxor    %xmm0, %xmm0
2034         sub     $0x1000, %r10
2035         jmp     LABEL(gobble_ashr_15)
2037         .p2align 4
2038 LABEL(ashr_15_exittail):
2039         movdqa  (%rsi, %rcx), %xmm1
2040         psrldq  $15, %xmm3
2041         psrldq  $15, %xmm0
2043         .p2align 4
2044 LABEL(aftertail):
2045         pcmpeqb %xmm3, %xmm1
2046         psubb   %xmm0, %xmm1
2047         pmovmskb %xmm1, %edx
2048         not     %edx
2050         .p2align 4
2051 LABEL(exit):
2052         lea     -16(%r9, %rcx), %rax    /* locate the exact offset for rdi */
2053 LABEL(less32bytes):
2054         lea     (%rdi, %rax), %rdi      /* locate the exact address for first operand(rdi) */
2055         lea     (%rsi, %rcx), %rsi      /* locate the exact address for second operand(rsi) */
2056         test    %r8d, %r8d
2057         jz      LABEL(ret)
2058         xchg    %rsi, %rdi              /* recover original order according to flag(%r8d) */
2060         .p2align 4
2061 LABEL(ret):
2062 LABEL(less16bytes):
2063         bsf     %rdx, %rdx              /* find and store bit index in %rdx */
2065 #ifdef USE_AS_STRNCMP
2066         sub     %rdx, %r11
2067         jbe     LABEL(strcmp_exitz)
2068 #endif
2069         movzbl  (%rsi, %rdx), %ecx
2070         movzbl  (%rdi, %rdx), %eax
2072         sub     %ecx, %eax
2073         ret
2075 LABEL(strcmp_exitz):
2076         xor     %eax, %eax
2077         ret
2079         .p2align 4
2080 LABEL(Byte0):
2081         movzx   (%rsi), %ecx
2082         movzx   (%rdi), %eax
2084         sub     %ecx, %eax
2085         ret
2086 END (BP_SYM (STRCMP))
2088         .section .rodata,"a",@progbits
2089         .p2align 3
2090 LABEL(unaligned_table):
2091         .int    LABEL(ashr_1) - LABEL(unaligned_table)
2092         .int    LABEL(ashr_2) - LABEL(unaligned_table)
2093         .int    LABEL(ashr_3) - LABEL(unaligned_table)
2094         .int    LABEL(ashr_4) - LABEL(unaligned_table)
2095         .int    LABEL(ashr_5) - LABEL(unaligned_table)
2096         .int    LABEL(ashr_6) - LABEL(unaligned_table)
2097         .int    LABEL(ashr_7) - LABEL(unaligned_table)
2098         .int    LABEL(ashr_8) - LABEL(unaligned_table)
2099         .int    LABEL(ashr_9) - LABEL(unaligned_table)
2100         .int    LABEL(ashr_10) - LABEL(unaligned_table)
2101         .int    LABEL(ashr_11) - LABEL(unaligned_table)
2102         .int    LABEL(ashr_12) - LABEL(unaligned_table)
2103         .int    LABEL(ashr_13) - LABEL(unaligned_table)
2104         .int    LABEL(ashr_14) - LABEL(unaligned_table)
2105         .int    LABEL(ashr_15) - LABEL(unaligned_table)
2106         .int    LABEL(ashr_0) - LABEL(unaligned_table)
2107 #endif /* NOT_IN_libc */
2108 libc_hidden_builtin_def (STRCMP)