Memory ordering in pthread_mutex_{,timed}lock.
[glibc.git] / sysdeps / x86_64 / multiarch / strcmp.S
blob15148e4f7fed3d5a8bfa062677b31b1b3fd91d56
1 /* strcmp with SSE4.2
2    Copyright (C) 2009 Free Software Foundation, Inc.
3    Contributed by Intel Corporation.
4    This file is part of the GNU C Library.
6    The GNU C Library is free software; you can redistribute it and/or
7    modify it under the terms of the GNU Lesser General Public
8    License as published by the Free Software Foundation; either
9    version 2.1 of the License, or (at your option) any later version.
11    The GNU C Library is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    Lesser General Public License for more details.
16    You should have received a copy of the GNU Lesser General Public
17    License along with the GNU C Library; if not, write to the Free
18    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19    02111-1307 USA.  */
21 #include <sysdep.h>
22 #include <ifunc-defines.h>
24 #ifdef USE_AS_STRNCMP
25 /* Since the counter, %r11, is unsigned, we branch to strcmp_exitz
26    if the new counter > the old one or is 0.  */
27 #define UPDATE_STRNCMP_COUNTER                          \
28         /* calculate left number to compare */          \
29         lea     -16(%rcx, %r11), %r9;                   \
30         cmp     %r9, %r11;                              \
31         jb      LABEL(strcmp_exitz);                    \
32         test    %r9, %r9;                               \
33         je      LABEL(strcmp_exitz);                    \
34         mov     %r9, %r11
36 #define STRCMP_SSE42    __strncmp_sse42
37 #define STRCMP_SSE2     __strncmp_sse2
38 #define __GI_STRCMP     __GI_strncmp
39 #else
40 #define UPDATE_STRNCMP_COUNTER
41 #ifndef STRCMP
42 #define STRCMP          strcmp
43 #define STRCMP_SSE42    __strcmp_sse42
44 #define STRCMP_SSE2     __strcmp_sse2
45 #define __GI_STRCMP     __GI_strcmp
46 #endif
47 #endif
49 #ifndef LABEL
50 #define LABEL(l) L(l)
51 #endif
53 /* Define multiple versions only for the definition in libc.  Don't
54    define multiple versions for strncmp in static library since we
55    need strncmp before the initialization happened.  */
56 #if (defined SHARED || !defined USE_AS_STRNCMP) && !defined NOT_IN_libc
57         .text
58 ENTRY(STRCMP)
59         .type   STRCMP, @gnu_indirect_function
60         cmpl    $0, __cpu_features+KIND_OFFSET(%rip)
61         jne     1f
62         call    __init_cpu_features
63 1:      leaq    STRCMP_SSE2(%rip), %rax
64         testl   $(1<<20), __cpu_features+CPUID_OFFSET+COMMON_CPUID_INDEX_1*CPUID_SIZE+CPUID_ECX_OFFSET(%rip)
65         jz      2f
66         leaq    STRCMP_SSE42(%rip), %rax
67 2:      ret
68 END(STRCMP)
70 /* We use 0x1a:
71         _SIDD_SBYTE_OPS
72         | _SIDD_CMP_EQUAL_EACH
73         | _SIDD_NEGATIVE_POLARITY
74         | _SIDD_LEAST_SIGNIFICANT
75    on pcmpistri to find out if two 16byte data elements are the same
76    and the offset of the first different byte.  There are 4 cases:
78    1. Both 16byte data elements are valid and identical.
79    2. Both 16byte data elements have EOS and identical.
80    3. Both 16byte data elements are valid and they differ at offset X.
81    4. At least one 16byte data element has EOS at offset X.  Two 16byte
82       data elements must differ at or before offset X.
84    Here is the table of ECX, CFlag, ZFlag and SFlag for 4 cases:
86    case         ECX     CFlag   ZFlag   SFlag
87     1           16        0       0       0
88     2           16        0       1       1
89     3            X        1       0       0
90     4          0 <= X     1      0/1     0/1
92    We exit from the loop for cases 2, 3 and 4 with jbe which branches
93    when either CFlag or ZFlag is 1.  If CFlag == 0, we return 0 for
94    case 2.  */
96         /* Put all SSE 4.2 functions together.  */
97         .section .text.sse4.2,"ax",@progbits
98         .align  16
99         .type   STRCMP_SSE42, @function
100 STRCMP_SSE42:
101         cfi_startproc
102         CALL_MCOUNT
105  * This implementation uses SSE to compare up to 16 bytes at a time.
106  */
107 #ifdef USE_AS_STRNCMP
108         test    %rdx, %rdx
109         je      LABEL(strcmp_exitz)
110         cmp     $1, %rdx
111         je      LABEL(Byte0)
112         mov     %rdx, %r11
113 #endif
114         mov     %esi, %ecx
115         mov     %edi, %eax
116 /* Use 64bit AND here to avoid long NOP padding.  */
117         and     $0x3f, %rcx             /* rsi alignment in cache line */
118         and     $0x3f, %rax             /* rdi alignment in cache line */
119         cmp     $0x30, %ecx
120         ja      LABEL(crosscache)       /* rsi: 16-byte load will cross cache line */
121         cmp     $0x30, %eax
122         ja      LABEL(crosscache)       /* rdi: 16-byte load will cross cache line */
123         movdqu  (%rdi), %xmm1
124         movdqu  (%rsi), %xmm2
125         pxor    %xmm0, %xmm0            /* clear %xmm0 for null char checks */
126         pcmpeqb %xmm1, %xmm0            /* Any null chars? */
127         pcmpeqb %xmm2, %xmm1            /* compare first 16 bytes for equality */
128         psubb   %xmm0, %xmm1            /* packed sub of comparison results*/
129         pmovmskb %xmm1, %edx
130         sub     $0xffff, %edx           /* if first 16 bytes are same, edx == 0xffff */
131         jnz     LABEL(less16bytes)      /* If not, find different value or null char */
132 #ifdef USE_AS_STRNCMP
133         sub     $16, %r11
134         jbe     LABEL(strcmp_exitz)     /* finish comparision */
135 #endif
136         add     $16, %rsi               /* prepare to search next 16 bytes */
137         add     $16, %rdi               /* prepare to search next 16 bytes */
139         /*
140          * Determine source and destination string offsets from 16-byte alignment.
141          * Use relative offset difference between the two to determine which case
142          * below to use.
143          */
144         .p2align 4
145 LABEL(crosscache):
146         and     $0xfffffffffffffff0, %rsi       /* force %rsi is 16 byte aligned */
147         and     $0xfffffffffffffff0, %rdi       /* force %rdi is 16 byte aligned */
148         mov     $0xffff, %edx                   /* for equivalent offset */
149         xor     %r8d, %r8d
150         and     $0xf, %ecx                      /* offset of rsi */
151         and     $0xf, %eax                      /* offset of rdi */
152         cmp     %eax, %ecx
153         je      LABEL(ashr_0)                   /* rsi and rdi relative offset same */
154         ja      LABEL(bigger)
155         mov     %edx, %r8d                      /* r8d is offset flag for exit tail */
156         xchg    %ecx, %eax
157         xchg    %rsi, %rdi
158 LABEL(bigger):
159         lea     15(%rax), %r9
160         sub     %rcx, %r9
161         lea     LABEL(unaligned_table)(%rip), %r10
162         movslq  (%r10, %r9,4), %r9
163         lea     (%r10, %r9), %r10
164         jmp     *%r10                           /* jump to corresponding case */
167  * The following cases will be handled by ashr_0
168  *  rcx(offset of rsi)  rax(offset of rdi)  relative offset  corresponding case
169  *        n(0~15)            n(0~15)           15(15+ n-n)         ashr_0
170  */
171         .p2align 4
172 LABEL(ashr_0):
174         movdqa  (%rsi), %xmm1
175         pxor    %xmm0, %xmm0                    /* clear %xmm0 for null char check */
176         pcmpeqb %xmm1, %xmm0                    /* Any null chars? */
177         pcmpeqb (%rdi), %xmm1                   /* compare 16 bytes for equality */
178         psubb   %xmm0, %xmm1                    /* packed sub of comparison results*/
179         pmovmskb %xmm1, %r9d
180         shr     %cl, %edx                       /* adjust 0xffff for offset */
181         shr     %cl, %r9d                       /* adjust for 16-byte offset */
182         sub     %r9d, %edx
183         /*
184          * edx must be the same with r9d if in left byte (16-rcx) is equal to
185          * the start from (16-rax) and no null char was seen.
186          */
187         jne     LABEL(less32bytes)              /* mismatch or null char */
188         UPDATE_STRNCMP_COUNTER
189         mov     $16, %rcx
190         mov     $16, %r9
191         pxor    %xmm0, %xmm0                    /* clear xmm0, may have changed above */
193         /*
194          * Now both strings are aligned at 16-byte boundary. Loop over strings
195          * checking 32-bytes per iteration.
196          */
197         mov     %rcx, %rdx      /* only for offset of sse4 instruction loop*/
198         .p2align 4
199 LABEL(ashr_0_use_sse4_2):
200         movdqa  (%rdi,%rdx), %xmm0
201         pcmpistri      $0x1a,(%rsi,%rdx), %xmm0
202         lea     16(%rdx), %rdx
203         jbe     LABEL(ashr_0_use_sse4_2_exit)
204 #ifdef USE_AS_STRNCMP
205         sub     $16, %r11
206         jbe     LABEL(strcmp_exitz)
207 #endif
209         movdqa  (%rdi,%rdx), %xmm0
210         pcmpistri      $0x1a,(%rsi,%rdx), %xmm0
211         lea     16(%rdx), %rdx
212         jbe     LABEL(ashr_0_use_sse4_2_exit)
213 #ifdef USE_AS_STRNCMP
214         sub     $16, %r11
215         jbe     LABEL(strcmp_exitz)
216 #endif
217         jmp     LABEL(ashr_0_use_sse4_2)
220         .p2align 4
221 LABEL(ashr_0_use_sse4_2_exit):
222         jnc     LABEL(strcmp_exitz)
223 #ifdef USE_AS_STRNCMP
224         sub     %rcx, %r11
225         jbe     LABEL(strcmp_exitz)
226 #endif
227         lea     -16(%rdx, %rcx), %rcx
228         movzbl  (%rdi, %rcx), %eax
229         movzbl  (%rsi, %rcx), %edx
230         sub     %edx, %eax
231         ret
237  * The following cases will be handled by ashr_1
238  * rcx(offset of rsi)  rax(offset of rdi)   relative offset     corresponding case
239  *        n(15)            n -15            0(15 +(n-15) - n)         ashr_1
240  */
241         .p2align 4
242 LABEL(ashr_1):
243         pxor    %xmm0, %xmm0
244         movdqa  (%rdi), %xmm2
245         movdqa  (%rsi), %xmm1
246         pcmpeqb %xmm1, %xmm0            /* Any null chars? */
247         pslldq  $15, %xmm2              /* shift first string to align with second */
248         pcmpeqb %xmm1, %xmm2            /* compare 16 bytes for equality */
249         psubb   %xmm0, %xmm2            /* packed sub of comparison results*/
250         pmovmskb %xmm2, %r9d
251         shr     %cl, %edx               /* adjust 0xffff for offset */
252         shr     %cl, %r9d               /* adjust for 16-byte offset */
253         sub     %r9d, %edx
254         jnz     LABEL(less32bytes)      /* mismatch or null char seen */
255         movdqa  (%rdi), %xmm3
256         UPDATE_STRNCMP_COUNTER
258         pxor    %xmm0, %xmm0
259         mov     $16, %rcx               /* index for loads*/
260         mov     $1, %r9d                /* byte position left over from less32bytes case */
261         /*
262          * Setup %r10 value allows us to detect crossing a page boundary.
263          * When %r10 goes positive we have crossed a page boundary and
264          * need to do a nibble.
265          */
266         lea     1(%rdi), %r10
267         and     $0xfff, %r10            /* offset into 4K page */
268         sub     $0x1000, %r10           /* subtract 4K pagesize */
269         mov     %rcx, %rdx      /* only for offset of sse4 instruction loop*/
271         .p2align 4
272 LABEL(loop_ashr_1_use_sse4_2):
273         add     $16, %r10
274         jg      LABEL(nibble_ashr_1_use_sse4_2)
276         movdqa  (%rdi, %rdx), %xmm0
277         palignr $1, -16(%rdi, %rdx), %xmm0
278         pcmpistri       $0x1a,(%rsi,%rdx), %xmm0
279         jbe     LABEL(use_sse4_2_exit)
280 #ifdef USE_AS_STRNCMP
281         sub     $16, %r11
282         jbe     LABEL(strcmp_exitz)
283 #endif
285         add     $16, %rdx
286         add     $16, %r10
287         jg      LABEL(nibble_ashr_1_use_sse4_2)
289         movdqa  (%rdi, %rdx), %xmm0
290         palignr $1, -16(%rdi, %rdx), %xmm0
291         pcmpistri       $0x1a,(%rsi,%rdx), %xmm0
292         jbe     LABEL(use_sse4_2_exit)
293 #ifdef USE_AS_STRNCMP
294         sub     $16, %r11
295         jbe     LABEL(strcmp_exitz)
296 #endif
297         add     $16, %rdx
298         jmp     LABEL(loop_ashr_1_use_sse4_2)
300         .p2align 4
301 LABEL(nibble_ashr_1_use_sse4_2):
302         sub     $0x1000, %r10
303         movdqa  -16(%rdi, %rdx), %xmm0
304         psrldq  $1, %xmm0
305         pcmpistri      $0x3a,%xmm0, %xmm0
306 #ifdef USE_AS_STRNCMP
307         cmp     %r11, %rcx
308         jae     LABEL(nibble_ashr_use_sse4_2_exit)
309 #endif
310         cmp     $14, %ecx
311         ja      LABEL(loop_ashr_1_use_sse4_2)
313         jmp     LABEL(nibble_ashr_use_sse4_2_exit)
316  * The following cases will be handled by ashr_2
317  * rcx(offset of rsi)  rax(offset of rdi)   relative offset     corresponding case
318  *        n(14~15)            n -14         1(15 +(n-14) - n)         ashr_2
319  */
320         .p2align 4
321 LABEL(ashr_2):
322         pxor    %xmm0, %xmm0
323         movdqa  (%rdi), %xmm2
324         movdqa  (%rsi), %xmm1
325         pcmpeqb %xmm1, %xmm0
326         pslldq  $14, %xmm2
327         pcmpeqb %xmm1, %xmm2
328         psubb   %xmm0, %xmm2
329         pmovmskb %xmm2, %r9d
330         shr     %cl, %edx
331         shr     %cl, %r9d
332         sub     %r9d, %edx
333         jnz     LABEL(less32bytes)
334         movdqa  (%rdi), %xmm3
335         UPDATE_STRNCMP_COUNTER
337         pxor    %xmm0, %xmm0
338         mov     $16, %rcx       /* index for loads */
339         mov     $2, %r9d        /* byte position left over from less32bytes case */
340         /*
341          * Setup %r10 value allows us to detect crossing a page boundary.
342          * When %r10 goes positive we have crossed a page boundary and
343          * need to do a nibble.
344          */
345         lea     2(%rdi), %r10
346         and     $0xfff, %r10    /* offset into 4K page */
347         sub     $0x1000, %r10   /* subtract 4K pagesize */
348         mov     %rcx, %rdx      /* only for offset of sse4 instruction loop*/
350         .p2align 4
351 LABEL(loop_ashr_2_use_sse4_2):
352         add     $16, %r10
353         jg      LABEL(nibble_ashr_2_use_sse4_2)
355         movdqa  (%rdi, %rdx), %xmm0
356         palignr $2, -16(%rdi, %rdx), %xmm0
357         pcmpistri       $0x1a,(%rsi,%rdx), %xmm0
358         jbe     LABEL(use_sse4_2_exit)
359 #ifdef USE_AS_STRNCMP
360         sub     $16, %r11
361         jbe     LABEL(strcmp_exitz)
362 #endif
364         add     $16, %rdx
365         add     $16, %r10
366         jg      LABEL(nibble_ashr_2_use_sse4_2)
368         movdqa  (%rdi, %rdx), %xmm0
369         palignr $2, -16(%rdi, %rdx), %xmm0
370         pcmpistri       $0x1a,(%rsi,%rdx), %xmm0
371         jbe     LABEL(use_sse4_2_exit)
372 #ifdef USE_AS_STRNCMP
373         sub     $16, %r11
374         jbe     LABEL(strcmp_exitz)
375 #endif
376         add     $16, %rdx
377         jmp     LABEL(loop_ashr_2_use_sse4_2)
379         .p2align 4
380 LABEL(nibble_ashr_2_use_sse4_2):
381         sub     $0x1000, %r10
382         movdqa  -16(%rdi, %rdx), %xmm0
383         psrldq  $2, %xmm0
384         pcmpistri      $0x3a,%xmm0, %xmm0
385 #ifdef USE_AS_STRNCMP
386         cmp     %r11, %rcx
387         jae     LABEL(nibble_ashr_use_sse4_2_exit)
388 #endif
389         cmp     $13, %ecx
390         ja      LABEL(loop_ashr_2_use_sse4_2)
392         jmp     LABEL(nibble_ashr_use_sse4_2_exit)
395  * The following cases will be handled by ashr_3
396  *  rcx(offset of rsi)  rax(offset of rdi)  relative offset      corresponding case
397  *        n(13~15)            n -13         2(15 +(n-13) - n)         ashr_3
398  */
399         .p2align 4
400 LABEL(ashr_3):
401         pxor    %xmm0, %xmm0
402         movdqa  (%rdi), %xmm2
403         movdqa  (%rsi), %xmm1
404         pcmpeqb %xmm1, %xmm0
405         pslldq  $13, %xmm2
406         pcmpeqb %xmm1, %xmm2
407         psubb   %xmm0, %xmm2
408         pmovmskb %xmm2, %r9d
409         shr     %cl, %edx
410         shr     %cl, %r9d
411         sub     %r9d, %edx
412         jnz     LABEL(less32bytes)
413         movdqa  (%rdi), %xmm3
415         UPDATE_STRNCMP_COUNTER
417         pxor    %xmm0, %xmm0
418         mov     $16, %rcx       /* index for loads */
419         mov     $3, %r9d        /* byte position left over from less32bytes case */
420         /*
421          * Setup %r10 value allows us to detect crossing a page boundary.
422          * When %r10 goes positive we have crossed a page boundary and
423          * need to do a nibble.
424          */
425         lea     3(%rdi), %r10
426         and     $0xfff, %r10    /* offset into 4K page */
427         sub     $0x1000, %r10   /* subtract 4K pagesize */
428         mov     %rcx, %rdx      /* only for offset of sse4 instruction loop*/
430 LABEL(loop_ashr_3_use_sse4_2):
431         add     $16, %r10
432         jg      LABEL(nibble_ashr_3_use_sse4_2)
434         movdqa  (%rdi, %rdx), %xmm0
435         palignr $3, -16(%rdi, %rdx), %xmm0
436         pcmpistri       $0x1a,(%rsi,%rdx), %xmm0
437         jbe     LABEL(use_sse4_2_exit)
438 #ifdef USE_AS_STRNCMP
439         sub     $16, %r11
440         jbe     LABEL(strcmp_exitz)
441 #endif
443         add     $16, %rdx
444         add     $16, %r10
445         jg      LABEL(nibble_ashr_3_use_sse4_2)
447         movdqa  (%rdi, %rdx), %xmm0
448         palignr $3, -16(%rdi, %rdx), %xmm0
449         pcmpistri       $0x1a,(%rsi,%rdx), %xmm0
450         jbe     LABEL(use_sse4_2_exit)
451 #ifdef USE_AS_STRNCMP
452         sub     $16, %r11
453         jbe     LABEL(strcmp_exitz)
454 #endif
455         add     $16, %rdx
456         jmp     LABEL(loop_ashr_3_use_sse4_2)
458         .p2align 4
459 LABEL(nibble_ashr_3_use_sse4_2):
460         sub     $0x1000, %r10
461         movdqa  -16(%rdi, %rdx), %xmm0
462         psrldq  $3, %xmm0
463         pcmpistri      $0x3a,%xmm0, %xmm0
464 #ifdef USE_AS_STRNCMP
465         cmp     %r11, %rcx
466         jae     LABEL(nibble_ashr_use_sse4_2_exit)
467 #endif
468         cmp     $12, %ecx
469         ja      LABEL(loop_ashr_3_use_sse4_2)
471         jmp     LABEL(nibble_ashr_use_sse4_2_exit)
474  * The following cases will be handled by ashr_4
475  *  rcx(offset of rsi)  rax(offset of rdi)  relative offset      corresponding case
476  *        n(12~15)            n -12         3(15 +(n-12) - n)         ashr_4
477  */
478         .p2align 4
479 LABEL(ashr_4):
480         pxor    %xmm0, %xmm0
481         movdqa  (%rdi), %xmm2
482         movdqa  (%rsi), %xmm1
483         pcmpeqb %xmm1, %xmm0
484         pslldq  $12, %xmm2
485         pcmpeqb %xmm1, %xmm2
486         psubb   %xmm0, %xmm2
487         pmovmskb %xmm2, %r9d
488         shr     %cl, %edx
489         shr     %cl, %r9d
490         sub     %r9d, %edx
491         jnz     LABEL(less32bytes)
492         movdqa  (%rdi), %xmm3
494         UPDATE_STRNCMP_COUNTER
496         pxor    %xmm0, %xmm0
497         mov     $16, %rcx       /* index for loads */
498         mov     $4, %r9d        /* byte position left over from less32bytes case */
499         /*
500          * Setup %r10 value allows us to detect crossing a page boundary.
501          * When %r10 goes positive we have crossed a page boundary and
502          * need to do a nibble.
503          */
504         lea     4(%rdi), %r10
505         and     $0xfff, %r10    /* offset into 4K page */
506         sub     $0x1000, %r10   /* subtract 4K pagesize */
507         mov     %rcx, %rdx      /* only for offset of sse4 instruction loop*/
509         .p2align 4
510 LABEL(loop_ashr_4_use_sse4_2):
511         add     $16, %r10
512         jg      LABEL(nibble_ashr_4_use_sse4_2)
514         movdqa  (%rdi, %rdx), %xmm0
515         palignr $4, -16(%rdi, %rdx), %xmm0
516         pcmpistri       $0x1a,(%rsi,%rdx), %xmm0
517         jbe     LABEL(use_sse4_2_exit)
518 #ifdef USE_AS_STRNCMP
519         sub     $16, %r11
520         jbe     LABEL(strcmp_exitz)
521 #endif
523         add     $16, %rdx
524         add     $16, %r10
525         jg      LABEL(nibble_ashr_4_use_sse4_2)
527         movdqa  (%rdi, %rdx), %xmm0
528         palignr $4, -16(%rdi, %rdx), %xmm0
529         pcmpistri       $0x1a,(%rsi,%rdx), %xmm0
530         jbe     LABEL(use_sse4_2_exit)
531 #ifdef USE_AS_STRNCMP
532         sub     $16, %r11
533         jbe     LABEL(strcmp_exitz)
534 #endif
535         add     $16, %rdx
536         jmp     LABEL(loop_ashr_4_use_sse4_2)
538         .p2align 4
539 LABEL(nibble_ashr_4_use_sse4_2):
540         sub     $0x1000, %r10
541         movdqa  -16(%rdi, %rdx), %xmm0
542         psrldq  $4, %xmm0
543         pcmpistri      $0x3a,%xmm0, %xmm0
544 #ifdef USE_AS_STRNCMP
545         cmp     %r11, %rcx
546         jae     LABEL(nibble_ashr_use_sse4_2_exit)
547 #endif
548         cmp     $11, %ecx
549         ja      LABEL(loop_ashr_4_use_sse4_2)
551         jmp     LABEL(nibble_ashr_use_sse4_2_exit)
554  * The following cases will be handled by ashr_5
555  *  rcx(offset of rsi)  rax(offset of rdi)        relative offset      corresponding case
556  *        n(11~15)          n - 11                4(15 +(n-11) - n)         ashr_5
557  */
558         .p2align 4
559 LABEL(ashr_5):
560         pxor    %xmm0, %xmm0
561         movdqa  (%rdi), %xmm2
562         movdqa  (%rsi), %xmm1
563         pcmpeqb %xmm1, %xmm0
564         pslldq  $11, %xmm2
565         pcmpeqb %xmm1, %xmm2
566         psubb   %xmm0, %xmm2
567         pmovmskb %xmm2, %r9d
568         shr     %cl, %edx
569         shr     %cl, %r9d
570         sub     %r9d, %edx
571         jnz     LABEL(less32bytes)
572         movdqa  (%rdi), %xmm3
574         UPDATE_STRNCMP_COUNTER
576         pxor    %xmm0, %xmm0
577         mov     $16, %rcx       /* index for loads */
578         mov     $5, %r9d        /* byte position left over from less32bytes case */
579         /*
580          * Setup %r10 value allows us to detect crossing a page boundary.
581          * When %r10 goes positive we have crossed a page boundary and
582          * need to do a nibble.
583          */
584         lea     5(%rdi), %r10
585         and     $0xfff, %r10    /* offset into 4K page */
586         sub     $0x1000, %r10   /* subtract 4K pagesize */
587         mov     %rcx, %rdx      /* only for offset of sse4 instruction loop*/
589         .p2align 4
590 LABEL(loop_ashr_5_use_sse4_2):
591         add     $16, %r10
592         jg      LABEL(nibble_ashr_5_use_sse4_2)
594         movdqa  (%rdi, %rdx), %xmm0
595         palignr $5, -16(%rdi, %rdx), %xmm0
596         pcmpistri       $0x1a,(%rsi,%rdx), %xmm0
597         jbe     LABEL(use_sse4_2_exit)
598 #ifdef USE_AS_STRNCMP
599         sub     $16, %r11
600         jbe     LABEL(strcmp_exitz)
601 #endif
603         add     $16, %rdx
604         add     $16, %r10
605         jg      LABEL(nibble_ashr_5_use_sse4_2)
607         movdqa  (%rdi, %rdx), %xmm0
609         palignr $5, -16(%rdi, %rdx), %xmm0
610         pcmpistri       $0x1a,(%rsi,%rdx), %xmm0
611         jbe     LABEL(use_sse4_2_exit)
612 #ifdef USE_AS_STRNCMP
613         sub     $16, %r11
614         jbe     LABEL(strcmp_exitz)
615 #endif
616         add     $16, %rdx
617         jmp     LABEL(loop_ashr_5_use_sse4_2)
619         .p2align 4
620 LABEL(nibble_ashr_5_use_sse4_2):
621         sub     $0x1000, %r10
622         movdqa  -16(%rdi, %rdx), %xmm0
623         psrldq  $5, %xmm0
624         pcmpistri      $0x3a,%xmm0, %xmm0
625 #ifdef USE_AS_STRNCMP
626         cmp     %r11, %rcx
627         jae     LABEL(nibble_ashr_use_sse4_2_exit)
628 #endif
629         cmp     $10, %ecx
630         ja      LABEL(loop_ashr_5_use_sse4_2)
632         jmp     LABEL(nibble_ashr_use_sse4_2_exit)
635  * The following cases will be handled by ashr_6
636  *  rcx(offset of rsi)  rax(offset of rdi)        relative offset      corresponding case
637  *        n(10~15)          n - 10                5(15 +(n-10) - n)         ashr_6
638  */
639         .p2align 4
640 LABEL(ashr_6):
641         pxor    %xmm0, %xmm0
642         movdqa  (%rdi), %xmm2
643         movdqa  (%rsi), %xmm1
644         pcmpeqb %xmm1, %xmm0
645         pslldq  $10, %xmm2
646         pcmpeqb %xmm1, %xmm2
647         psubb   %xmm0, %xmm2
648         pmovmskb %xmm2, %r9d
649         shr     %cl, %edx
650         shr     %cl, %r9d
651         sub     %r9d, %edx
652         jnz     LABEL(less32bytes)
653         movdqa  (%rdi), %xmm3
655         UPDATE_STRNCMP_COUNTER
657         pxor    %xmm0, %xmm0
658         mov     $16, %rcx       /* index for loads */
659         mov     $6, %r9d        /* byte position left over from less32bytes case */
660         /*
661          * Setup %r10 value allows us to detect crossing a page boundary.
662          * When %r10 goes positive we have crossed a page boundary and
663          * need to do a nibble.
664          */
665         lea     6(%rdi), %r10
666         and     $0xfff, %r10    /* offset into 4K page */
667         sub     $0x1000, %r10   /* subtract 4K pagesize */
668         mov     %rcx, %rdx      /* only for offset of sse4 instruction loop*/
670         .p2align 4
671 LABEL(loop_ashr_6_use_sse4_2):
672         add     $16, %r10
673         jg      LABEL(nibble_ashr_6_use_sse4_2)
675         movdqa  (%rdi, %rdx), %xmm0
676         palignr $6, -16(%rdi, %rdx), %xmm0
677         pcmpistri       $0x1a,(%rsi,%rdx), %xmm0
678         jbe     LABEL(use_sse4_2_exit)
679 #ifdef USE_AS_STRNCMP
680         sub     $16, %r11
681         jbe     LABEL(strcmp_exitz)
682 #endif
684         add     $16, %rdx
685         add     $16, %r10
686         jg      LABEL(nibble_ashr_6_use_sse4_2)
688         movdqa  (%rdi, %rdx), %xmm0
689         palignr $6, -16(%rdi, %rdx), %xmm0
690         pcmpistri       $0x1a,(%rsi,%rdx), %xmm0
691         jbe     LABEL(use_sse4_2_exit)
692 #ifdef USE_AS_STRNCMP
693         sub     $16, %r11
694         jbe     LABEL(strcmp_exitz)
695 #endif
696         add     $16, %rdx
697         jmp     LABEL(loop_ashr_6_use_sse4_2)
699         .p2align 4
700 LABEL(nibble_ashr_6_use_sse4_2):
701         sub     $0x1000, %r10
702         movdqa  -16(%rdi, %rdx), %xmm0
703         psrldq  $6, %xmm0
704         pcmpistri      $0x3a,%xmm0, %xmm0
705 #ifdef USE_AS_STRNCMP
706         cmp     %r11, %rcx
707         jae     LABEL(nibble_ashr_use_sse4_2_exit)
708 #endif
709         cmp     $9, %ecx
710         ja      LABEL(loop_ashr_6_use_sse4_2)
712         jmp     LABEL(nibble_ashr_use_sse4_2_exit)
715  * The following cases will be handled by ashr_7
716  *  rcx(offset of rsi)  rax(offset of rdi)        relative offset      corresponding case
717  *        n(9~15)          n - 9                6(15 +(n - 9) - n)         ashr_7
718  */
719         .p2align 4
720 LABEL(ashr_7):
721         pxor    %xmm0, %xmm0
722         movdqa  (%rdi), %xmm2
723         movdqa  (%rsi), %xmm1
724         pcmpeqb %xmm1, %xmm0
725         pslldq  $9, %xmm2
726         pcmpeqb %xmm1, %xmm2
727         psubb   %xmm0, %xmm2
728         pmovmskb %xmm2, %r9d
729         shr     %cl, %edx
730         shr     %cl, %r9d
731         sub     %r9d, %edx
732         jnz     LABEL(less32bytes)
733         movdqa  (%rdi), %xmm3
735         UPDATE_STRNCMP_COUNTER
737         pxor    %xmm0, %xmm0
738         mov     $16, %rcx       /* index for loads */
739         mov     $7, %r9d        /* byte position left over from less32bytes case */
740         /*
741          * Setup %r10 value allows us to detect crossing a page boundary.
742          * When %r10 goes positive we have crossed a page boundary and
743          * need to do a nibble.
744          */
745         lea     7(%rdi), %r10
746         and     $0xfff, %r10    /* offset into 4K page */
747         sub     $0x1000, %r10   /* subtract 4K pagesize */
748         mov     %rcx, %rdx      /* only for offset of sse4 instruction loop*/
750         .p2align 4
751 LABEL(loop_ashr_7_use_sse4_2):
752         add     $16, %r10
753         jg      LABEL(nibble_ashr_7_use_sse4_2)
755         movdqa  (%rdi, %rdx), %xmm0
756         palignr $7, -16(%rdi, %rdx), %xmm0
757         pcmpistri       $0x1a,(%rsi,%rdx), %xmm0
758         jbe     LABEL(use_sse4_2_exit)
759 #ifdef USE_AS_STRNCMP
760         sub     $16, %r11
761         jbe     LABEL(strcmp_exitz)
762 #endif
764         add     $16, %rdx
765         add     $16, %r10
766         jg      LABEL(nibble_ashr_7_use_sse4_2)
768         movdqa  (%rdi, %rdx), %xmm0
769         palignr $7, -16(%rdi, %rdx), %xmm0
770         pcmpistri       $0x1a,(%rsi,%rdx), %xmm0
771         jbe     LABEL(use_sse4_2_exit)
772 #ifdef USE_AS_STRNCMP
773         sub     $16, %r11
774         jbe     LABEL(strcmp_exitz)
775 #endif
776         add     $16, %rdx
777         jmp     LABEL(loop_ashr_7_use_sse4_2)
779         .p2align 4
780 LABEL(nibble_ashr_7_use_sse4_2):
781         sub     $0x1000, %r10
782         movdqa  -16(%rdi, %rdx), %xmm0
783         psrldq  $7, %xmm0
784         pcmpistri      $0x3a,%xmm0, %xmm0
785 #ifdef USE_AS_STRNCMP
786         cmp     %r11, %rcx
787         jae     LABEL(nibble_ashr_use_sse4_2_exit)
788 #endif
789         cmp     $8, %ecx
790         ja      LABEL(loop_ashr_7_use_sse4_2)
792         jmp     LABEL(nibble_ashr_use_sse4_2_exit)
795  *  The following cases will be handled by ashr_8
796  *  rcx(offset of rsi)  rax(offset of rdi)        relative offset        corresponding case
797  *        n(8~15)          n - 8                7(15 +(n - 8) - n)         ashr_8
798  */
799         .p2align 4
800 LABEL(ashr_8):
801         pxor    %xmm0, %xmm0
802         movdqa  (%rdi), %xmm2
803         movdqa  (%rsi), %xmm1
804         pcmpeqb %xmm1, %xmm0
805         pslldq  $8, %xmm2
806         pcmpeqb %xmm1, %xmm2
807         psubb   %xmm0, %xmm2
808         pmovmskb %xmm2, %r9d
809         shr     %cl, %edx
810         shr     %cl, %r9d
811         sub     %r9d, %edx
812         jnz     LABEL(less32bytes)
813         movdqa  (%rdi), %xmm3
815         UPDATE_STRNCMP_COUNTER
817         pxor    %xmm0, %xmm0
818         mov     $16, %rcx       /* index for loads */
819         mov     $8, %r9d        /* byte position left over from less32bytes case */
820         /*
821          * Setup %r10 value allows us to detect crossing a page boundary.
822          * When %r10 goes positive we have crossed a page boundary and
823          * need to do a nibble.
824          */
825         lea     8(%rdi), %r10
826         and     $0xfff, %r10    /* offset into 4K page */
827         sub     $0x1000, %r10   /* subtract 4K pagesize */
828         mov     %rcx, %rdx      /* only for offset of sse4 instruction loop*/
830         .p2align 4
831 LABEL(loop_ashr_8_use_sse4_2):
832         add     $16, %r10
833         jg      LABEL(nibble_ashr_8_use_sse4_2)
835         movdqa  (%rdi, %rdx), %xmm0
836         palignr $8, -16(%rdi, %rdx), %xmm0
837         pcmpistri       $0x1a,(%rsi,%rdx), %xmm0
838         jbe     LABEL(use_sse4_2_exit)
839 #ifdef USE_AS_STRNCMP
840         sub     $16, %r11
841         jbe     LABEL(strcmp_exitz)
842 #endif
844         add     $16, %rdx
845         add     $16, %r10
846         jg      LABEL(nibble_ashr_8_use_sse4_2)
848         movdqa  (%rdi, %rdx), %xmm0
849         palignr $8, -16(%rdi, %rdx), %xmm0
850         pcmpistri       $0x1a,(%rsi,%rdx), %xmm0
851         jbe     LABEL(use_sse4_2_exit)
852 #ifdef USE_AS_STRNCMP
853         sub     $16, %r11
854         jbe     LABEL(strcmp_exitz)
855 #endif
856         add     $16, %rdx
857         jmp     LABEL(loop_ashr_8_use_sse4_2)
859         .p2align 4
860 LABEL(nibble_ashr_8_use_sse4_2):
861         sub     $0x1000, %r10
862         movdqa  -16(%rdi, %rdx), %xmm0
863         psrldq  $8, %xmm0
864         pcmpistri      $0x3a,%xmm0, %xmm0
865 #ifdef USE_AS_STRNCMP
866         cmp     %r11, %rcx
867         jae     LABEL(nibble_ashr_use_sse4_2_exit)
868 #endif
869         cmp     $7, %ecx
870         ja      LABEL(loop_ashr_8_use_sse4_2)
872         jmp     LABEL(nibble_ashr_use_sse4_2_exit)
875  *  The following cases will be handled by ashr_9
876  *  rcx(offset of rsi)  rax(offset of rdi)        relative offset        corresponding case
877  *        n(7~15)          n - 7                8(15 +(n - 7) - n)         ashr_9
878  */
879         .p2align 4
880 LABEL(ashr_9):
881         pxor    %xmm0, %xmm0
882         movdqa  (%rdi), %xmm2
883         movdqa  (%rsi), %xmm1
884         pcmpeqb %xmm1, %xmm0
885         pslldq  $7, %xmm2
886         pcmpeqb %xmm1, %xmm2
887         psubb   %xmm0, %xmm2
888         pmovmskb %xmm2, %r9d
889         shr     %cl, %edx
890         shr     %cl, %r9d
891         sub     %r9d, %edx
892         jnz     LABEL(less32bytes)
893         movdqa  (%rdi), %xmm3
895         UPDATE_STRNCMP_COUNTER
897         pxor    %xmm0, %xmm0
898         mov     $16, %rcx       /* index for loads */
899         mov     $9, %r9d        /* byte position left over from less32bytes case */
900         /*
901          * Setup %r10 value allows us to detect crossing a page boundary.
902          * When %r10 goes positive we have crossed a page boundary and
903          * need to do a nibble.
904          */
905         lea     9(%rdi), %r10
906         and     $0xfff, %r10    /* offset into 4K page */
907         sub     $0x1000, %r10   /* subtract 4K pagesize */
908         mov     %rcx, %rdx      /* only for offset of sse4 instruction loop*/
910         .p2align 4
911 LABEL(loop_ashr_9_use_sse4_2):
912         add     $16, %r10
913         jg      LABEL(nibble_ashr_9_use_sse4_2)
915         movdqa  (%rdi, %rdx), %xmm0
917         palignr $9, -16(%rdi, %rdx), %xmm0
918         pcmpistri       $0x1a,(%rsi,%rdx), %xmm0
919         jbe     LABEL(use_sse4_2_exit)
920 #ifdef USE_AS_STRNCMP
921         sub     $16, %r11
922         jbe     LABEL(strcmp_exitz)
923 #endif
925         add     $16, %rdx
926         add     $16, %r10
927         jg      LABEL(nibble_ashr_9_use_sse4_2)
929         movdqa  (%rdi, %rdx), %xmm0
930         palignr $9, -16(%rdi, %rdx), %xmm0
931         pcmpistri       $0x1a,(%rsi,%rdx), %xmm0
932         jbe     LABEL(use_sse4_2_exit)
933 #ifdef USE_AS_STRNCMP
934         sub     $16, %r11
935         jbe     LABEL(strcmp_exitz)
936 #endif
937         add     $16, %rdx
938         jmp     LABEL(loop_ashr_9_use_sse4_2)
940         .p2align 4
941 LABEL(nibble_ashr_9_use_sse4_2):
942         sub     $0x1000, %r10
943         movdqa  -16(%rdi, %rdx), %xmm0
944         psrldq  $9, %xmm0
945         pcmpistri      $0x3a,%xmm0, %xmm0
946 #ifdef USE_AS_STRNCMP
947         cmp     %r11, %rcx
948         jae     LABEL(nibble_ashr_use_sse4_2_exit)
949 #endif
950         cmp     $6, %ecx
951         ja      LABEL(loop_ashr_9_use_sse4_2)
953         jmp     LABEL(nibble_ashr_use_sse4_2_exit)
956  *  The following cases will be handled by ashr_10
957  *  rcx(offset of rsi)  rax(offset of rdi)        relative offset        corresponding case
958  *        n(6~15)          n - 6                9(15 +(n - 6) - n)         ashr_10
959  */
960         .p2align 4
961 LABEL(ashr_10):
962         pxor    %xmm0, %xmm0
963         movdqa  (%rdi), %xmm2
964         movdqa  (%rsi), %xmm1
965         pcmpeqb %xmm1, %xmm0
966         pslldq  $6, %xmm2
967         pcmpeqb %xmm1, %xmm2
968         psubb   %xmm0, %xmm2
969         pmovmskb %xmm2, %r9d
970         shr     %cl, %edx
971         shr     %cl, %r9d
972         sub     %r9d, %edx
973         jnz     LABEL(less32bytes)
974         movdqa  (%rdi), %xmm3
976         UPDATE_STRNCMP_COUNTER
978         pxor    %xmm0, %xmm0
979         mov     $16, %rcx       /* index for loads */
980         mov     $10, %r9d       /* byte position left over from less32bytes case */
981         /*
982          * Setup %r10 value allows us to detect crossing a page boundary.
983          * When %r10 goes positive we have crossed a page boundary and
984          * need to do a nibble.
985          */
986         lea     10(%rdi), %r10
987         and     $0xfff, %r10    /* offset into 4K page */
988         sub     $0x1000, %r10   /* subtract 4K pagesize */
989         mov     %rcx, %rdx      /* only for offset of sse4 instruction loop*/
991         .p2align 4
992 LABEL(loop_ashr_10_use_sse4_2):
993         add     $16, %r10
994         jg      LABEL(nibble_ashr_10_use_sse4_2)
996         movdqa  (%rdi, %rdx), %xmm0
997         palignr $10, -16(%rdi, %rdx), %xmm0
998         pcmpistri       $0x1a,(%rsi,%rdx), %xmm0
999         jbe     LABEL(use_sse4_2_exit)
1000 #ifdef USE_AS_STRNCMP
1001         sub     $16, %r11
1002         jbe     LABEL(strcmp_exitz)
1003 #endif
1005         add     $16, %rdx
1006         add     $16, %r10
1007         jg      LABEL(nibble_ashr_10_use_sse4_2)
1009         movdqa  (%rdi, %rdx), %xmm0
1010         palignr $10, -16(%rdi, %rdx), %xmm0
1011         pcmpistri       $0x1a,(%rsi,%rdx), %xmm0
1012         jbe     LABEL(use_sse4_2_exit)
1013 #ifdef USE_AS_STRNCMP
1014         sub     $16, %r11
1015         jbe     LABEL(strcmp_exitz)
1016 #endif
1017         add     $16, %rdx
1018         jmp     LABEL(loop_ashr_10_use_sse4_2)
1020         .p2align 4
1021 LABEL(nibble_ashr_10_use_sse4_2):
1022         sub     $0x1000, %r10
1023         movdqa  -16(%rdi, %rdx), %xmm0
1024         psrldq  $10, %xmm0
1025         pcmpistri      $0x3a,%xmm0, %xmm0
1026 #ifdef USE_AS_STRNCMP
1027         cmp     %r11, %rcx
1028         jae     LABEL(nibble_ashr_use_sse4_2_exit)
1029 #endif
1030         cmp     $5, %ecx
1031         ja      LABEL(loop_ashr_10_use_sse4_2)
1033         jmp     LABEL(nibble_ashr_use_sse4_2_exit)
1036  *  The following cases will be handled by ashr_11
1037  *  rcx(offset of rsi)  rax(offset of rdi)        relative offset        corresponding case
1038  *        n(5~15)          n - 5                10(15 +(n - 5) - n)         ashr_11
1039  */
1040         .p2align 4
1041 LABEL(ashr_11):
1042         pxor    %xmm0, %xmm0
1043         movdqa  (%rdi), %xmm2
1044         movdqa  (%rsi), %xmm1
1045         pcmpeqb %xmm1, %xmm0
1046         pslldq  $5, %xmm2
1047         pcmpeqb %xmm1, %xmm2
1048         psubb   %xmm0, %xmm2
1049         pmovmskb %xmm2, %r9d
1050         shr     %cl, %edx
1051         shr     %cl, %r9d
1052         sub     %r9d, %edx
1053         jnz     LABEL(less32bytes)
1054         movdqa  (%rdi), %xmm3
1056         UPDATE_STRNCMP_COUNTER
1058         pxor    %xmm0, %xmm0
1059         mov     $16, %rcx       /* index for loads */
1060         mov     $11, %r9d       /* byte position left over from less32bytes case */
1061         /*
1062          * Setup %r10 value allows us to detect crossing a page boundary.
1063          * When %r10 goes positive we have crossed a page boundary and
1064          * need to do a nibble.
1065          */
1066         lea     11(%rdi), %r10
1067         and     $0xfff, %r10    /* offset into 4K page */
1068         sub     $0x1000, %r10   /* subtract 4K pagesize */
1069         mov     %rcx, %rdx      /* only for offset of sse4 instruction loop*/
1071         .p2align 4
1072 LABEL(loop_ashr_11_use_sse4_2):
1073         add     $16, %r10
1074         jg      LABEL(nibble_ashr_11_use_sse4_2)
1076         movdqa  (%rdi, %rdx), %xmm0
1077         palignr $11, -16(%rdi, %rdx), %xmm0
1078         pcmpistri       $0x1a,(%rsi,%rdx), %xmm0
1079         jbe     LABEL(use_sse4_2_exit)
1080 #ifdef USE_AS_STRNCMP
1081         sub     $16, %r11
1082         jbe     LABEL(strcmp_exitz)
1083 #endif
1085         add     $16, %rdx
1086         add     $16, %r10
1087         jg      LABEL(nibble_ashr_11_use_sse4_2)
1089         movdqa  (%rdi, %rdx), %xmm0
1090         palignr $11, -16(%rdi, %rdx), %xmm0
1091         pcmpistri       $0x1a,(%rsi,%rdx), %xmm0
1092         jbe     LABEL(use_sse4_2_exit)
1093 #ifdef USE_AS_STRNCMP
1094         sub     $16, %r11
1095         jbe     LABEL(strcmp_exitz)
1096 #endif
1097         add     $16, %rdx
1098         jmp     LABEL(loop_ashr_11_use_sse4_2)
1100         .p2align 4
1101 LABEL(nibble_ashr_11_use_sse4_2):
1102         sub     $0x1000, %r10
1103         movdqa  -16(%rdi, %rdx), %xmm0
1104         psrldq  $11, %xmm0
1105         pcmpistri      $0x3a,%xmm0, %xmm0
1106 #ifdef USE_AS_STRNCMP
1107         cmp     %r11, %rcx
1108         jae     LABEL(nibble_ashr_use_sse4_2_exit)
1109 #endif
1110         cmp     $4, %ecx
1111         ja      LABEL(loop_ashr_11_use_sse4_2)
1113         jmp     LABEL(nibble_ashr_use_sse4_2_exit)
1116  *  The following cases will be handled by ashr_12
1117  *  rcx(offset of rsi)  rax(offset of rdi)        relative offset        corresponding case
1118  *        n(4~15)          n - 4                11(15 +(n - 4) - n)         ashr_12
1119  */
1120         .p2align 4
1121 LABEL(ashr_12):
1122         pxor    %xmm0, %xmm0
1123         movdqa  (%rdi), %xmm2
1124         movdqa  (%rsi), %xmm1
1125         pcmpeqb %xmm1, %xmm0
1126         pslldq  $4, %xmm2
1127         pcmpeqb %xmm1, %xmm2
1128         psubb   %xmm0, %xmm2
1129         pmovmskb %xmm2, %r9d
1130         shr     %cl, %edx
1131         shr     %cl, %r9d
1132         sub     %r9d, %edx
1133         jnz     LABEL(less32bytes)
1134         movdqa  (%rdi), %xmm3
1136         UPDATE_STRNCMP_COUNTER
1138         pxor    %xmm0, %xmm0
1139         mov     $16, %rcx       /* index for loads */
1140         mov     $12, %r9d       /* byte position left over from less32bytes case */
1141         /*
1142          * Setup %r10 value allows us to detect crossing a page boundary.
1143          * When %r10 goes positive we have crossed a page boundary and
1144          * need to do a nibble.
1145          */
1146         lea     12(%rdi), %r10
1147         and     $0xfff, %r10    /* offset into 4K page */
1148         sub     $0x1000, %r10   /* subtract 4K pagesize */
1149         mov     %rcx, %rdx      /* only for offset of sse4 instruction loop*/
1151         .p2align 4
1152 LABEL(loop_ashr_12_use_sse4_2):
1153         add     $16, %r10
1154         jg      LABEL(nibble_ashr_12_use_sse4_2)
1156         movdqa  (%rdi, %rdx), %xmm0
1157         palignr $12, -16(%rdi, %rdx), %xmm0
1158         pcmpistri       $0x1a,(%rsi,%rdx), %xmm0
1159         jbe     LABEL(use_sse4_2_exit)
1160 #ifdef USE_AS_STRNCMP
1161         sub     $16, %r11
1162         jbe     LABEL(strcmp_exitz)
1163 #endif
1165         add     $16, %rdx
1166         add     $16, %r10
1167         jg      LABEL(nibble_ashr_12_use_sse4_2)
1169         movdqa  (%rdi, %rdx), %xmm0
1170         palignr $12, -16(%rdi, %rdx), %xmm0
1171         pcmpistri       $0x1a,(%rsi,%rdx), %xmm0
1172         jbe     LABEL(use_sse4_2_exit)
1173 #ifdef USE_AS_STRNCMP
1174         sub     $16, %r11
1175         jbe     LABEL(strcmp_exitz)
1176 #endif
1177         add     $16, %rdx
1178         jmp     LABEL(loop_ashr_12_use_sse4_2)
1180         .p2align 4
1181 LABEL(nibble_ashr_12_use_sse4_2):
1182         sub     $0x1000, %r10
1183         movdqa  -16(%rdi, %rdx), %xmm0
1184         psrldq  $12, %xmm0
1185         pcmpistri      $0x3a,%xmm0, %xmm0
1186 #ifdef USE_AS_STRNCMP
1187         cmp     %r11, %rcx
1188         jae     LABEL(nibble_ashr_use_sse4_2_exit)
1189 #endif
1190         cmp     $3, %ecx
1191         ja      LABEL(loop_ashr_12_use_sse4_2)
1193         jmp     LABEL(nibble_ashr_use_sse4_2_exit)
1196  *  The following cases will be handled by ashr_13
1197  *  rcx(offset of rsi)  rax(offset of rdi)        relative offset        corresponding case
1198  *        n(3~15)          n - 3                12(15 +(n - 3) - n)         ashr_13
1199  */
1200         .p2align 4
1201 LABEL(ashr_13):
1202         pxor    %xmm0, %xmm0
1203         movdqa  (%rdi), %xmm2
1204         movdqa  (%rsi), %xmm1
1205         pcmpeqb %xmm1, %xmm0
1206         pslldq  $3, %xmm2
1207         pcmpeqb %xmm1, %xmm2
1208         psubb   %xmm0, %xmm2
1209         pmovmskb %xmm2, %r9d
1210         shr     %cl, %edx
1211         shr     %cl, %r9d
1212         sub     %r9d, %edx
1213         jnz     LABEL(less32bytes)
1214         movdqa  (%rdi), %xmm3
1216         UPDATE_STRNCMP_COUNTER
1218         pxor    %xmm0, %xmm0
1219         mov     $16, %rcx       /* index for loads */
1220         mov     $13, %r9d       /* byte position left over from less32bytes case */
1221         /*
1222          * Setup %r10 value allows us to detect crossing a page boundary.
1223          * When %r10 goes positive we have crossed a page boundary and
1224          * need to do a nibble.
1225          */
1226         lea     13(%rdi), %r10
1227         and     $0xfff, %r10    /* offset into 4K page */
1228         sub     $0x1000, %r10   /* subtract 4K pagesize */
1230         mov     %rcx, %rdx      /* only for offset of sse4 instruction loop*/
1232         .p2align 4
1233 LABEL(loop_ashr_13_use_sse4_2):
1234         add     $16, %r10
1235         jg      LABEL(nibble_ashr_13_use_sse4_2)
1237         movdqa  (%rdi, %rdx), %xmm0
1238         palignr $13, -16(%rdi, %rdx), %xmm0
1239         pcmpistri       $0x1a,(%rsi,%rdx), %xmm0
1240         jbe     LABEL(use_sse4_2_exit)
1241 #ifdef USE_AS_STRNCMP
1242         sub     $16, %r11
1243         jbe     LABEL(strcmp_exitz)
1244 #endif
1246         add     $16, %rdx
1247         add     $16, %r10
1248         jg      LABEL(nibble_ashr_13_use_sse4_2)
1250         movdqa  (%rdi, %rdx), %xmm0
1251         palignr $13, -16(%rdi, %rdx), %xmm0
1252         pcmpistri       $0x1a,(%rsi,%rdx), %xmm0
1253         jbe     LABEL(use_sse4_2_exit)
1254 #ifdef USE_AS_STRNCMP
1255         sub     $16, %r11
1256         jbe     LABEL(strcmp_exitz)
1257 #endif
1258         add     $16, %rdx
1259         jmp     LABEL(loop_ashr_13_use_sse4_2)
1261         .p2align 4
1262 LABEL(nibble_ashr_13_use_sse4_2):
1263         sub     $0x1000, %r10
1264         movdqa  -16(%rdi, %rdx), %xmm0
1265         psrldq  $13, %xmm0
1266         pcmpistri      $0x3a,%xmm0, %xmm0
1267 #ifdef USE_AS_STRNCMP
1268         cmp     %r11, %rcx
1269         jae     LABEL(nibble_ashr_use_sse4_2_exit)
1270 #endif
1271         cmp     $2, %ecx
1272         ja      LABEL(loop_ashr_13_use_sse4_2)
1274         jmp     LABEL(nibble_ashr_use_sse4_2_exit)
1277  *  The following cases will be handled by ashr_14
1278  *  rcx(offset of rsi)  rax(offset of rdi)        relative offset        corresponding case
1279  *        n(2~15)          n - 2                13(15 +(n - 2) - n)         ashr_14
1280  */
1281         .p2align 4
1282 LABEL(ashr_14):
1283         pxor    %xmm0, %xmm0
1284         movdqa  (%rdi), %xmm2
1285         movdqa  (%rsi), %xmm1
1286         pcmpeqb %xmm1, %xmm0
1287         pslldq  $2, %xmm2
1288         pcmpeqb %xmm1, %xmm2
1289         psubb   %xmm0, %xmm2
1290         pmovmskb %xmm2, %r9d
1291         shr     %cl, %edx
1292         shr     %cl, %r9d
1293         sub     %r9d, %edx
1294         jnz     LABEL(less32bytes)
1295         movdqa  (%rdi), %xmm3
1297         UPDATE_STRNCMP_COUNTER
1299         pxor    %xmm0, %xmm0
1300         mov     $16, %rcx       /* index for loads */
1301         mov     $14, %r9d       /* byte position left over from less32bytes case */
1302         /*
1303          * Setup %r10 value allows us to detect crossing a page boundary.
1304          * When %r10 goes positive we have crossed a page boundary and
1305          * need to do a nibble.
1306          */
1307         lea     14(%rdi), %r10
1308         and     $0xfff, %r10    /* offset into 4K page */
1309         sub     $0x1000, %r10   /* subtract 4K pagesize */
1311         mov     %rcx, %rdx      /* only for offset of sse4 instruction loop*/
1313         .p2align 4
1314 LABEL(loop_ashr_14_use_sse4_2):
1315         add     $16, %r10
1316         jg      LABEL(nibble_ashr_14_use_sse4_2)
1318         movdqa  (%rdi, %rdx), %xmm0
1319         palignr $14, -16(%rdi, %rdx), %xmm0
1320         pcmpistri       $0x1a,(%rsi,%rdx), %xmm0
1321         jbe     LABEL(use_sse4_2_exit)
1322 #ifdef USE_AS_STRNCMP
1323         sub     $16, %r11
1324         jbe     LABEL(strcmp_exitz)
1325 #endif
1327         add     $16, %rdx
1328         add     $16, %r10
1329         jg      LABEL(nibble_ashr_14_use_sse4_2)
1331         movdqa  (%rdi, %rdx), %xmm0
1332         palignr $14, -16(%rdi, %rdx), %xmm0
1333         pcmpistri       $0x1a,(%rsi,%rdx), %xmm0
1334         jbe     LABEL(use_sse4_2_exit)
1335 #ifdef USE_AS_STRNCMP
1336         sub     $16, %r11
1337         jbe     LABEL(strcmp_exitz)
1338 #endif
1339         add     $16, %rdx
1340         jmp     LABEL(loop_ashr_14_use_sse4_2)
1342         .p2align 4
1343 LABEL(nibble_ashr_14_use_sse4_2):
1344         sub     $0x1000, %r10
1345         movdqa  -16(%rdi, %rdx), %xmm0
1346         psrldq  $14, %xmm0
1347         pcmpistri      $0x3a,%xmm0, %xmm0
1348 #ifdef USE_AS_STRNCMP
1349         cmp     %r11, %rcx
1350         jae     LABEL(nibble_ashr_use_sse4_2_exit)
1351 #endif
1352         cmp     $1, %ecx
1353         ja      LABEL(loop_ashr_14_use_sse4_2)
1355         jmp     LABEL(nibble_ashr_use_sse4_2_exit)
1358  *  The following cases will be handled by ashr_15
1359  *  rcx(offset of rsi)  rax(offset of rdi)        relative offset        corresponding case
1360  *        n(1~15)          n - 1                14(15 +(n - 1) - n)         ashr_15
1361  */
1362         .p2align 4
1363 LABEL(ashr_15):
1364         pxor    %xmm0, %xmm0
1365         movdqa  (%rdi), %xmm2
1366         movdqa  (%rsi), %xmm1
1367         pcmpeqb %xmm1, %xmm0
1368         pslldq  $1, %xmm2
1369         pcmpeqb %xmm1, %xmm2
1370         psubb   %xmm0, %xmm2
1371         pmovmskb %xmm2, %r9d
1372         shr     %cl, %edx
1373         shr     %cl, %r9d
1374         sub     %r9d, %edx
1375         jnz     LABEL(less32bytes)
1377         movdqa  (%rdi), %xmm3
1379         UPDATE_STRNCMP_COUNTER
1381         pxor    %xmm0, %xmm0
1382         mov     $16, %rcx       /* index for loads */
1383         mov     $15, %r9d       /* byte position left over from less32bytes case */
1384         /*
1385          * Setup %r10 value allows us to detect crossing a page boundary.
1386          * When %r10 goes positive we have crossed a page boundary and
1387          * need to do a nibble.
1388          */
1389         lea     15(%rdi), %r10
1390         and     $0xfff, %r10    /* offset into 4K page */
1392         sub     $0x1000, %r10   /* subtract 4K pagesize */
1394         mov     %rcx, %rdx      /* only for offset of sse4 instruction loop*/
1396         .p2align 4
1397 LABEL(loop_ashr_15_use_sse4_2):
1398         add     $16, %r10
1399         jg      LABEL(nibble_ashr_15_use_sse4_2)
1401         movdqa  (%rdi, %rdx), %xmm0
1402         palignr $15, -16(%rdi, %rdx), %xmm0
1403         pcmpistri      $0x1a,(%rsi,%rdx), %xmm0
1404         jbe     LABEL(use_sse4_2_exit)
1405 #ifdef USE_AS_STRNCMP
1406         sub     $16, %r11
1407         jbe     LABEL(strcmp_exitz)
1408 #endif
1410         add     $16, %rdx
1411         add     $16, %r10
1412         jg      LABEL(nibble_ashr_15_use_sse4_2)
1414         movdqa  (%rdi, %rdx), %xmm0
1415         palignr $15, -16(%rdi, %rdx), %xmm0
1416         pcmpistri      $0x1a,(%rsi,%rdx), %xmm0
1417         jbe     LABEL(use_sse4_2_exit)
1418 #ifdef USE_AS_STRNCMP
1419         sub     $16, %r11
1420         jbe     LABEL(strcmp_exitz)
1421 #endif
1422         add     $16, %rdx
1423         jmp     LABEL(loop_ashr_15_use_sse4_2)
1425         .p2align 4
1426 LABEL(nibble_ashr_15_use_sse4_2):
1427         sub     $0x1000, %r10
1428         movdqa  -16(%rdi, %rdx), %xmm0
1429         psrldq  $15, %xmm0
1430         pcmpistri      $0x3a,%xmm0, %xmm0
1431 #ifdef USE_AS_STRNCMP
1432         cmp     %r11, %rcx
1433         jae     LABEL(nibble_ashr_use_sse4_2_exit)
1434 #endif
1435         cmp     $0, %ecx
1436         ja      LABEL(loop_ashr_15_use_sse4_2)
1438 LABEL(nibble_ashr_use_sse4_2_exit):
1439         pcmpistri      $0x1a,(%rsi,%rdx), %xmm0
1440         .p2align 4
1441 LABEL(use_sse4_2_exit):
1442         jnc     LABEL(strcmp_exitz)
1443 #ifdef USE_AS_STRNCMP
1444         sub     %rcx, %r11
1445         jbe     LABEL(strcmp_exitz)
1446 #endif
1447         add     %rcx, %rdx
1448         lea     -16(%rdi, %r9), %rdi
1449         movzbl  (%rdi, %rdx), %eax
1450         movzbl  (%rsi, %rdx), %edx
1451         test    %r8d, %r8d
1452         jz      LABEL(use_sse4_2_ret)
1453         xchg    %eax, %edx
1454 LABEL(use_sse4_2_ret):
1455         sub     %edx, %eax
1456         ret
1458 #if 0
1459         /* This code was in the origial submission but isn't used.
1460            --drepper */
1461         .p2align 4
1462 LABEL(aftertail):
1463         pcmpeqb %xmm3, %xmm1
1464         psubb   %xmm0, %xmm1
1465         pmovmskb %xmm1, %edx
1466         not     %edx
1468         .p2align 4
1469 LABEL(exit):
1470         lea     -16(%r9, %rcx), %rax    /* locate the exact offset for rdi */
1471 #endif
1473 LABEL(less32bytes):
1474         lea     (%rdi, %rax), %rdi      /* locate the exact address for first operand(rdi) */
1475         lea     (%rsi, %rcx), %rsi      /* locate the exact address for second operand(rsi) */
1476         test    %r8d, %r8d
1477         jz      LABEL(ret)
1478         xchg    %rsi, %rdi              /* recover original order according to flag(%r8d) */
1480         .p2align 4
1481 LABEL(ret):
1482 LABEL(less16bytes):
1483         /*
1484          * Check to see if BSF is fast on this processor. If not, use a different
1485          * exit tail.
1486          */
1487         bsf     %rdx, %rdx              /* find and store bit index in %rdx */
1489 #ifdef USE_AS_STRNCMP
1490         sub     %rdx, %r11
1491         jbe     LABEL(strcmp_exitz)
1492 #endif
1493         movzbl  (%rsi, %rdx), %ecx
1494         movzbl  (%rdi, %rdx), %eax
1496         sub     %ecx, %eax
1497         ret
1499 LABEL(strcmp_exitz):
1500         xor     %eax, %eax
1501         ret
1503         .p2align 4
1504 LABEL(Byte0):
1505         /*
1506          * never need to handle byte 0 for strncmpy
1507 #ifdef USE_AS_STRNCMP
1508         sub     $0, %r11
1509         jbe     LABEL(strcmp_exitz)
1510 #endif
1511         */
1512         movzx   (%rsi), %ecx
1513         movzx   (%rdi), %eax
1515         sub     %ecx, %eax
1516         ret
1518         .p2align 4
1519 LABEL(Byte1):
1521 #ifdef USE_AS_STRNCMP
1522         sub     $1, %r11
1523         jbe     LABEL(strcmp_exitz)
1524 #endif
1525         movzx   1(%rsi), %ecx
1526         movzx   1(%rdi), %eax
1528         sub     %ecx, %eax
1529         ret
1531         .p2align 4
1532 LABEL(Byte2):
1534 #ifdef USE_AS_STRNCMP
1535         sub     $2, %r11
1536         jbe     LABEL(strcmp_exitz)
1537 #endif
1538         movzx   2(%rsi), %ecx
1539         movzx   2(%rdi), %eax
1541         sub     %ecx, %eax
1542         ret
1544         .p2align 4
1545 LABEL(Byte3):
1547 #ifdef USE_AS_STRNCMP
1548         sub     $3, %r11
1549         jbe     LABEL(strcmp_exitz)
1550 #endif
1551         movzx   3(%rsi), %ecx
1552         movzx   3(%rdi), %eax
1554         sub     %ecx, %eax
1555         ret
1557         .p2align 4
1558 LABEL(Byte4):
1560 #ifdef USE_AS_STRNCMP
1561         sub     $4, %r11
1562         jbe     LABEL(strcmp_exitz)
1563 #endif
1564         movzx   4(%rsi), %ecx
1565         movzx   4(%rdi), %eax
1567         sub     %ecx, %eax
1568         ret
1570         .p2align 4
1571 LABEL(Byte5):
1573 #ifdef USE_AS_STRNCMP
1574         sub     $5, %r11
1575         jbe     LABEL(strcmp_exitz)
1576 #endif
1577         movzx   5(%rsi), %ecx
1578         movzx   5(%rdi), %eax
1580         sub     %ecx, %eax
1581         ret
1583         .p2align 4
1584 LABEL(Byte6):
1586 #ifdef USE_AS_STRNCMP
1587         sub     $6, %r11
1588         jbe     LABEL(strcmp_exitz)
1589 #endif
1590         movzx   6(%rsi), %ecx
1591         movzx   6(%rdi), %eax
1593         sub     %ecx, %eax
1594         ret
1596         .p2align 4
1597 LABEL(next_8_bytes):
1598         add     $8, %rdi
1599         add     $8, %rsi
1600 #ifdef USE_AS_STRNCMP
1601         sub     $8, %r11
1602         jbe     LABEL(strcmp_exitz)
1603 #endif
1604         test    $0x01, %dh
1605         jnz     LABEL(Byte0)
1607         test    $0x02, %dh
1608         jnz     LABEL(Byte1)
1610         test    $0x04, %dh
1611         jnz     LABEL(Byte2)
1613         test    $0x08, %dh
1614         jnz     LABEL(Byte3)
1616         test    $0x10, %dh
1617         jnz     LABEL(Byte4)
1619         test    $0x20, %dh
1620         jnz     LABEL(Byte5)
1622         test    $0x40, %dh
1623         jnz     LABEL(Byte6)
1625 #ifdef USE_AS_STRNCMP
1626         sub     $7, %r11
1627         jbe     LABEL(strcmp_exitz)
1628 #endif
1629         movzx   7(%rsi), %ecx
1630         movzx   7(%rdi), %eax
1632         sub     %ecx, %eax
1633         ret
1634         cfi_endproc
1635         .size   STRCMP_SSE42, .-STRCMP_SSE42
1637         /* Put all SSE 4.2 functions together.  */
1638         .section .rodata.sse4.2,"a",@progbits
1639         .p2align 4
1640 LABEL(unaligned_table):
1641         .int    LABEL(ashr_1) - LABEL(unaligned_table)
1642         .int    LABEL(ashr_2) - LABEL(unaligned_table)
1643         .int    LABEL(ashr_3) - LABEL(unaligned_table)
1644         .int    LABEL(ashr_4) - LABEL(unaligned_table)
1645         .int    LABEL(ashr_5) - LABEL(unaligned_table)
1646         .int    LABEL(ashr_6) - LABEL(unaligned_table)
1647         .int    LABEL(ashr_7) - LABEL(unaligned_table)
1648         .int    LABEL(ashr_8) - LABEL(unaligned_table)
1649         .int    LABEL(ashr_9) - LABEL(unaligned_table)
1650         .int    LABEL(ashr_10) - LABEL(unaligned_table)
1651         .int    LABEL(ashr_11) - LABEL(unaligned_table)
1652         .int    LABEL(ashr_12) - LABEL(unaligned_table)
1653         .int    LABEL(ashr_13) - LABEL(unaligned_table)
1654         .int    LABEL(ashr_14) - LABEL(unaligned_table)
1655         .int    LABEL(ashr_15) - LABEL(unaligned_table)
1656         .int    LABEL(ashr_0) - LABEL(unaligned_table)
1659 # undef ENTRY
1660 # define ENTRY(name) \
1661         .type STRCMP_SSE2, @function; \
1662         .align 16; \
1663         STRCMP_SSE2: cfi_startproc; \
1664         CALL_MCOUNT
1665 # undef END
1666 # define END(name) \
1667         cfi_endproc; .size STRCMP_SSE2, .-STRCMP_SSE2
1668 # undef libc_hidden_builtin_def
1669 /* It doesn't make sense to send libc-internal strcmp calls through a PLT.
1670    The speedup we get from using SSE4.2 instruction is likely eaten away
1671    by the indirect call in the PLT.  */
1672 # define libc_hidden_builtin_def(name) \
1673         .globl __GI_STRCMP; __GI_STRCMP = STRCMP_SSE2
1674 #endif
1676 #ifndef USE_AS_STRNCMP
1677 #include "../strcmp.S"
1678 #endif