Add SSE2 support to str{,n}cmp for x86-64.
[glibc.git] / sysdeps / x86_64 / strcmp.S
blob340a64ba3551c4cee7d7eee93ce83c6c3fd5c478
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         .text
55 ENTRY (BP_SYM (STRCMP))
56 #ifdef NOT_IN_libc
57 /* Simple version since we can't use SSE registers in ld.so.  */
58 L(oop): movb    (%rdi), %al
59         cmpb    (%rsi), %al
60         jne     L(neq)
61         incq    %rdi
62         incq    %rsi
63         testb   %al, %al
64         jnz     L(oop)
66         xorl    %eax, %eax
67         ret
69 L(neq): movl    $1, %eax
70         movl    $-1, %ecx
71         cmovbl  %ecx, %eax
72         ret
73 END (BP_SYM (STRCMP))
74 #else   /* NOT_IN_libc */
76  * This implementation uses SSE to compare up to 16 bytes at a time.
77  */
78 #ifdef USE_AS_STRNCMP
79         test    %rdx, %rdx
80         je      LABEL(strcmp_exitz)
81         cmp     $1, %rdx
82         je      LABEL(Byte0)
83         mov     %rdx, %r11
84 #endif
85         mov     %esi, %ecx
86         mov     %edi, %eax
87 /* Use 64bit AND here to avoid long NOP padding.  */
88         and     $0x3f, %rcx             /* rsi alignment in cache line */
89         and     $0x3f, %rax             /* rdi alignment in cache line */
90         cmp     $0x30, %ecx
91         ja      LABEL(crosscache)       /* rsi: 16-byte load will cross cache line */
92         cmp     $0x30, %eax
93         ja      LABEL(crosscache)       /* rdi: 16-byte load will cross cache line */
94         movlpd  (%rdi), %xmm1
95         movlpd  (%rsi), %xmm2
96         movhpd  8(%rdi), %xmm1
97         movhpd  8(%rsi), %xmm2
98         pxor    %xmm0, %xmm0            /* clear %xmm0 for null char checks */
99         pcmpeqb %xmm1, %xmm0            /* Any null chars? */
100         pcmpeqb %xmm2, %xmm1            /* compare first 16 bytes for equality */
101         psubb   %xmm0, %xmm1            /* packed sub of comparison results*/
102         pmovmskb %xmm1, %edx
103         sub     $0xffff, %edx           /* if first 16 bytes are same, edx == 0xffff */
104         jnz     LABEL(less16bytes)      /* If not, find different value or null char */
105 #ifdef USE_AS_STRNCMP
106         sub     $16, %r11
107         jbe     LABEL(strcmp_exitz)     /* finish comparision */
108 #endif
109         add     $16, %rsi               /* prepare to search next 16 bytes */
110         add     $16, %rdi               /* prepare to search next 16 bytes */
112         /*
113          * Determine source and destination string offsets from 16-byte alignment.
114          * Use relative offset difference between the two to determine which case
115          * below to use.
116          */
117         .p2align 4
118 LABEL(crosscache):
119         and     $0xfffffffffffffff0, %rsi       /* force %rsi is 16 byte aligned */
120         and     $0xfffffffffffffff0, %rdi       /* force %rdi is 16 byte aligned */
121         mov     $0xffff, %edx                   /* for equivalent offset */
122         xor     %r8d, %r8d
123         and     $0xf, %ecx                      /* offset of rsi */
124         and     $0xf, %eax                      /* offset of rdi */
125         cmp     %eax, %ecx
126         je      LABEL(ashr_0)                   /* rsi and rdi relative offset same */
127         ja      LABEL(bigger)
128         mov     %edx, %r8d                      /* r8d is offset flag for exit tail */
129         xchg    %ecx, %eax
130         xchg    %rsi, %rdi
131 LABEL(bigger):
132         lea     15(%rax), %r9
133         sub     %rcx, %r9
134         lea     LABEL(unaligned_table)(%rip), %r10
135         movslq  (%r10, %r9,4), %r9
136         lea     (%r10, %r9), %r10
137         jmp     *%r10                           /* jump to corresponding case */
140  * The following cases will be handled by ashr_0
141  *  rcx(offset of rsi)  rax(offset of rdi)  relative offset  corresponding case
142  *        n(0~15)            n(0~15)           15(15+ n-n)         ashr_0
143  */
144         .p2align 4
145 LABEL(ashr_0):
147         movdqa  (%rsi), %xmm1
148         pxor    %xmm0, %xmm0                    /* clear %xmm0 for null char check */
149         pcmpeqb %xmm1, %xmm0                    /* Any null chars? */
150         pcmpeqb (%rdi), %xmm1                   /* compare 16 bytes for equality */
151         psubb   %xmm0, %xmm1                    /* packed sub of comparison results*/
152         pmovmskb %xmm1, %r9d
153         shr     %cl, %edx                       /* adjust 0xffff for offset */
154         shr     %cl, %r9d                       /* adjust for 16-byte offset */
155         sub     %r9d, %edx
156         /*
157          * edx must be the same with r9d if in left byte (16-rcx) is equal to
158          * the start from (16-rax) and no null char was seen.
159          */
160         jne     LABEL(less32bytes)              /* mismatch or null char */
161         UPDATE_STRNCMP_COUNTER
162         mov     $16, %rcx
163         mov     $16, %r9
164         pxor    %xmm0, %xmm0                    /* clear xmm0, may have changed above */
166         /*
167          * Now both strings are aligned at 16-byte boundary. Loop over strings
168          * checking 32-bytes per iteration.
169          */
170         .p2align 4
171 LABEL(loop_ashr_0):
172         movdqa  (%rsi, %rcx), %xmm1
173         movdqa  (%rdi, %rcx), %xmm2
175         pcmpeqb %xmm1, %xmm0
176         pcmpeqb %xmm2, %xmm1
177         psubb   %xmm0, %xmm1
178         pmovmskb %xmm1, %edx
179         sub     $0xffff, %edx
180         jnz     LABEL(exit)             /* mismatch or null char seen */
182 #ifdef USE_AS_STRNCMP
183         sub     $16, %r11
184         jbe     LABEL(strcmp_exitz)
185 #endif
186         add     $16, %rcx
187         movdqa  (%rsi, %rcx), %xmm1
188         movdqa  (%rdi, %rcx), %xmm2
190         pcmpeqb %xmm1, %xmm0
191         pcmpeqb %xmm2, %xmm1
192         psubb   %xmm0, %xmm1
193         pmovmskb %xmm1, %edx
194         sub     $0xffff, %edx
195         jnz     LABEL(exit)
196 #ifdef USE_AS_STRNCMP
197         sub     $16, %r11
198         jbe     LABEL(strcmp_exitz)
199 #endif
200         add     $16, %rcx
201         jmp     LABEL(loop_ashr_0)
204  * The following cases will be handled by ashr_1
205  * rcx(offset of rsi)  rax(offset of rdi)   relative offset     corresponding case
206  *        n(15)            n -15            0(15 +(n-15) - n)         ashr_1
207  */
208         .p2align 4
209 LABEL(ashr_1):
210         pxor    %xmm0, %xmm0
211         movdqa  (%rdi), %xmm2
212         movdqa  (%rsi), %xmm1
213         pcmpeqb %xmm1, %xmm0            /* Any null chars? */
214         pslldq  $15, %xmm2              /* shift first string to align with second */
215         pcmpeqb %xmm1, %xmm2            /* compare 16 bytes for equality */
216         psubb   %xmm0, %xmm2            /* packed sub of comparison results*/
217         pmovmskb %xmm2, %r9d
218         shr     %cl, %edx               /* adjust 0xffff for offset */
219         shr     %cl, %r9d               /* adjust for 16-byte offset */
220         sub     %r9d, %edx
221         jnz     LABEL(less32bytes)      /* mismatch or null char seen */
222         movdqa  (%rdi), %xmm3
223         UPDATE_STRNCMP_COUNTER
225         pxor    %xmm0, %xmm0
226         mov     $16, %rcx               /* index for loads*/
227         mov     $1, %r9d                /* byte position left over from less32bytes case */
228         /*
229          * Setup %r10 value allows us to detect crossing a page boundary.
230          * When %r10 goes positive we have crossed a page boundary and
231          * need to do a nibble.
232          */
233         lea     1(%rdi), %r10
234         and     $0xfff, %r10            /* offset into 4K page */
235         sub     $0x1000, %r10           /* subtract 4K pagesize */
237         .p2align 4
238 LABEL(loop_ashr_1):
239         add     $16, %r10
240         jg      LABEL(nibble_ashr_1)    /* cross page boundary */
242 LABEL(gobble_ashr_1):
243         movdqa  (%rsi, %rcx), %xmm1
244         movdqa  (%rdi, %rcx), %xmm2
245         movdqa  %xmm2, %xmm4             /* store for next cycle */
247         psrldq  $1, %xmm3
248         pslldq  $15, %xmm2
249         por     %xmm3, %xmm2            /* merge into one 16byte value */
251         pcmpeqb %xmm1, %xmm0
252         pcmpeqb %xmm2, %xmm1
253         psubb   %xmm0, %xmm1
254         pmovmskb %xmm1, %edx
255         sub     $0xffff, %edx
256         jnz     LABEL(exit)
258 #ifdef USE_AS_STRNCMP
259         sub     $16, %r11
260         jbe     LABEL(strcmp_exitz)
261 #endif
262         add     $16, %rcx
263         movdqa  %xmm4, %xmm3
265         add     $16, %r10
266         jg      LABEL(nibble_ashr_1)    /* cross page boundary */
268         movdqa  (%rsi, %rcx), %xmm1
269         movdqa  (%rdi, %rcx), %xmm2
270         movdqa  %xmm2, %xmm4            /* store for next cycle */
272         psrldq  $1, %xmm3
273         pslldq  $15, %xmm2
274         por     %xmm3, %xmm2            /* merge into one 16byte value */
276         pcmpeqb %xmm1, %xmm0
277         pcmpeqb %xmm2, %xmm1
278         psubb   %xmm0, %xmm1
279         pmovmskb %xmm1, %edx
280         sub     $0xffff, %edx
281         jnz     LABEL(exit)
283 #ifdef USE_AS_STRNCMP
284         sub     $16, %r11
285         jbe     LABEL(strcmp_exitz)
286 #endif
287         add     $16, %rcx
288         movdqa  %xmm4, %xmm3
289         jmp     LABEL(loop_ashr_1)
291         /*
292          * Nibble avoids loads across page boundary. This is to avoid a potential
293          * access into unmapped memory.
294          */
295         .p2align 4
296 LABEL(nibble_ashr_1):
297         pcmpeqb %xmm3, %xmm0             /* check nibble for null char*/
298         pmovmskb %xmm0, %edx
299         test    $0xfffe, %edx
300         jnz     LABEL(ashr_1_exittail)  /* find null char*/
302 #ifdef USE_AS_STRNCMP
303         cmp     $14, %r11
304         jbe     LABEL(ashr_1_exittail)
305 #endif
307         pxor    %xmm0, %xmm0
308         sub     $0x1000, %r10           /* substract 4K from %r10 */
309         jmp     LABEL(gobble_ashr_1)
311         /*
312          * Once find null char, determine if there is a string mismatch
313          * before the null char.
314          */
315         .p2align 4
316 LABEL(ashr_1_exittail):
317         movdqa  (%rsi, %rcx), %xmm1
318         psrldq  $1, %xmm0
319         psrldq  $1, %xmm3
320         jmp     LABEL(aftertail)
323  * The following cases will be handled by ashr_2
324  * rcx(offset of rsi)  rax(offset of rdi)   relative offset     corresponding case
325  *        n(14~15)            n -14         1(15 +(n-14) - n)         ashr_2
326  */
327         .p2align 4
328 LABEL(ashr_2):
329         pxor    %xmm0, %xmm0
330         movdqa  (%rdi), %xmm2
331         movdqa  (%rsi), %xmm1
332         pcmpeqb %xmm1, %xmm0
333         pslldq  $14, %xmm2
334         pcmpeqb %xmm1, %xmm2
335         psubb   %xmm0, %xmm2
336         pmovmskb %xmm2, %r9d
337         shr     %cl, %edx
338         shr     %cl, %r9d
339         sub     %r9d, %edx
340         jnz     LABEL(less32bytes)
341         movdqa  (%rdi), %xmm3
342         UPDATE_STRNCMP_COUNTER
344         pxor    %xmm0, %xmm0
345         mov     $16, %rcx       /* index for loads */
346         mov     $2, %r9d        /* byte position left over from less32bytes case */
347         /*
348          * Setup %r10 value allows us to detect crossing a page boundary.
349          * When %r10 goes positive we have crossed a page boundary and
350          * need to do a nibble.
351          */
352         lea     2(%rdi), %r10
353         and     $0xfff, %r10    /* offset into 4K page */
354         sub     $0x1000, %r10   /* subtract 4K pagesize */
356         .p2align 4
357 LABEL(loop_ashr_2):
358         add     $16, %r10
359         jg      LABEL(nibble_ashr_2)
361 LABEL(gobble_ashr_2):
362         movdqa  (%rsi, %rcx), %xmm1
363         movdqa  (%rdi, %rcx), %xmm2
364         movdqa  %xmm2, %xmm4
366         psrldq  $2, %xmm3
367         pslldq  $14, %xmm2
368         por     %xmm3, %xmm2
370         pcmpeqb %xmm1, %xmm0
371         pcmpeqb %xmm2, %xmm1
372         psubb   %xmm0, %xmm1
373         pmovmskb %xmm1, %edx
374         sub     $0xffff, %edx
375         jnz     LABEL(exit)
377 #ifdef USE_AS_STRNCMP
378         sub     $16, %r11
379         jbe     LABEL(strcmp_exitz)
380 #endif
382         add     $16, %rcx
383         movdqa  %xmm4, %xmm3
385         add     $16, %r10
386         jg      LABEL(nibble_ashr_2)    /* cross page boundary */
388         movdqa  (%rsi, %rcx), %xmm1
389         movdqa  (%rdi, %rcx), %xmm2
390         movdqa  %xmm2, %xmm4
392         psrldq  $2, %xmm3
393         pslldq  $14, %xmm2
394         por     %xmm3, %xmm2
396         pcmpeqb %xmm1, %xmm0
397         pcmpeqb %xmm2, %xmm1
398         psubb   %xmm0, %xmm1
399         pmovmskb %xmm1, %edx
400         sub     $0xffff, %edx
401         jnz     LABEL(exit)
403 #ifdef USE_AS_STRNCMP
404         sub     $16, %r11
405         jbe     LABEL(strcmp_exitz)
406 #endif
408         add     $16, %rcx
409         movdqa  %xmm4, %xmm3
410         jmp     LABEL(loop_ashr_2)
412         .p2align 4
413 LABEL(nibble_ashr_2):
414         pcmpeqb %xmm3, %xmm0            /* check nibble for null char */
415         pmovmskb %xmm0, %edx
416         test    $0xfffc, %edx
417         jnz     LABEL(ashr_2_exittail)
419 #ifdef USE_AS_STRNCMP
420         cmp     $13, %r11
421         jbe     LABEL(ashr_2_exittail)
422 #endif
424         pxor    %xmm0, %xmm0
425         sub     $0x1000, %r10
426         jmp     LABEL(gobble_ashr_2)
428         .p2align 4
429 LABEL(ashr_2_exittail):
430         movdqa  (%rsi, %rcx), %xmm1
431         psrldq  $2, %xmm0
432         psrldq  $2, %xmm3
433         jmp     LABEL(aftertail)
436  * The following cases will be handled by ashr_3
437  *  rcx(offset of rsi)  rax(offset of rdi)  relative offset      corresponding case
438  *        n(13~15)            n -13         2(15 +(n-13) - n)         ashr_3
439  */
440         .p2align 4
441 LABEL(ashr_3):
442         pxor    %xmm0, %xmm0
443         movdqa  (%rdi), %xmm2
444         movdqa  (%rsi), %xmm1
445         pcmpeqb %xmm1, %xmm0
446         pslldq  $13, %xmm2
447         pcmpeqb %xmm1, %xmm2
448         psubb   %xmm0, %xmm2
449         pmovmskb %xmm2, %r9d
450         shr     %cl, %edx
451         shr     %cl, %r9d
452         sub     %r9d, %edx
453         jnz     LABEL(less32bytes)
454         movdqa  (%rdi), %xmm3
456         UPDATE_STRNCMP_COUNTER
458         pxor    %xmm0, %xmm0
459         mov     $16, %rcx       /* index for loads */
460         mov     $3, %r9d        /* byte position left over from less32bytes case */
461         /*
462          * Setup %r10 value allows us to detect crossing a page boundary.
463          * When %r10 goes positive we have crossed a page boundary and
464          * need to do a nibble.
465          */
466         lea     3(%rdi), %r10
467         and     $0xfff, %r10    /* offset into 4K page */
468         sub     $0x1000, %r10   /* subtract 4K pagesize */
470         .p2align 4
471 LABEL(loop_ashr_3):
472         add     $16, %r10
473         jg      LABEL(nibble_ashr_3)
475 LABEL(gobble_ashr_3):
476         movdqa  (%rsi, %rcx), %xmm1
477         movdqa  (%rdi, %rcx), %xmm2
478         movdqa  %xmm2, %xmm4
480         psrldq  $3, %xmm3
481         pslldq  $13, %xmm2
482         por     %xmm3, %xmm2
484         pcmpeqb %xmm1, %xmm0
485         pcmpeqb %xmm2, %xmm1
486         psubb   %xmm0, %xmm1
487         pmovmskb %xmm1, %edx
488         sub     $0xffff, %edx
489         jnz     LABEL(exit)
491 #ifdef USE_AS_STRNCMP
492         sub     $16, %r11
493         jbe     LABEL(strcmp_exitz)
494 #endif
496         add     $16, %rcx
497         movdqa  %xmm4, %xmm3
499         add     $16, %r10
500         jg      LABEL(nibble_ashr_3)    /* cross page boundary */
502         movdqa  (%rsi, %rcx), %xmm1
503         movdqa  (%rdi, %rcx), %xmm2
504         movdqa  %xmm2, %xmm4
506         psrldq  $3, %xmm3
507         pslldq  $13, %xmm2
508         por     %xmm3, %xmm2
510         pcmpeqb %xmm1, %xmm0
511         pcmpeqb %xmm2, %xmm1
512         psubb   %xmm0, %xmm1
513         pmovmskb %xmm1, %edx
514         sub     $0xffff, %edx
515         jnz     LABEL(exit)
517 #ifdef USE_AS_STRNCMP
518         sub     $16, %r11
519         jbe     LABEL(strcmp_exitz)
520 #endif
522         add     $16, %rcx
523         movdqa  %xmm4, %xmm3
524         jmp     LABEL(loop_ashr_3)
526         .p2align 4
527 LABEL(nibble_ashr_3):
528         pcmpeqb %xmm3, %xmm0            /* check nibble for null char */
529         pmovmskb %xmm0, %edx
530         test    $0xfff8, %edx
531         jnz     LABEL(ashr_3_exittail)
533 #ifdef USE_AS_STRNCMP
534         cmp     $12, %r11
535         jbe     LABEL(ashr_3_exittail)
536 #endif
538         pxor    %xmm0, %xmm0
539         sub     $0x1000, %r10
540         jmp     LABEL(gobble_ashr_3)
542         .p2align 4
543 LABEL(ashr_3_exittail):
544         movdqa  (%rsi, %rcx), %xmm1
545         psrldq  $3, %xmm0
546         psrldq  $3, %xmm3
547         jmp     LABEL(aftertail)
550  * The following cases will be handled by ashr_4
551  *  rcx(offset of rsi)  rax(offset of rdi)  relative offset      corresponding case
552  *        n(12~15)            n -12         3(15 +(n-12) - n)         ashr_4
553  */
554         .p2align 4
555 LABEL(ashr_4):
556         pxor    %xmm0, %xmm0
557         movdqa  (%rdi), %xmm2
558         movdqa  (%rsi), %xmm1
559         pcmpeqb %xmm1, %xmm0
560         pslldq  $12, %xmm2
561         pcmpeqb %xmm1, %xmm2
562         psubb   %xmm0, %xmm2
563         pmovmskb %xmm2, %r9d
564         shr     %cl, %edx
565         shr     %cl, %r9d
566         sub     %r9d, %edx
567         jnz     LABEL(less32bytes)
568         movdqa  (%rdi), %xmm3
570         UPDATE_STRNCMP_COUNTER
572         pxor    %xmm0, %xmm0
573         mov     $16, %rcx       /* index for loads */
574         mov     $4, %r9d        /* byte position left over from less32bytes case */
575         /*
576          * Setup %r10 value allows us to detect crossing a page boundary.
577          * When %r10 goes positive we have crossed a page boundary and
578          * need to do a nibble.
579          */
580         lea     4(%rdi), %r10
581         and     $0xfff, %r10    /* offset into 4K page */
582         sub     $0x1000, %r10   /* subtract 4K pagesize */
584         .p2align 4
585 LABEL(loop_ashr_4):
586         add     $16, %r10
587         jg      LABEL(nibble_ashr_4)
589 LABEL(gobble_ashr_4):
590         movdqa  (%rsi, %rcx), %xmm1
591         movdqa  (%rdi, %rcx), %xmm2
592         movdqa  %xmm2, %xmm4
594         psrldq  $4, %xmm3
595         pslldq  $12, %xmm2
596         por     %xmm3, %xmm2
598         pcmpeqb %xmm1, %xmm0
599         pcmpeqb %xmm2, %xmm1
600         psubb   %xmm0, %xmm1
601         pmovmskb %xmm1, %edx
602         sub     $0xffff, %edx
603         jnz     LABEL(exit)
605 #ifdef USE_AS_STRNCMP
606         sub     $16, %r11
607         jbe     LABEL(strcmp_exitz)
608 #endif
610         add     $16, %rcx
611         movdqa  %xmm4, %xmm3
613         add     $16, %r10
614         jg      LABEL(nibble_ashr_4)    /* cross page boundary */
616         movdqa  (%rsi, %rcx), %xmm1
617         movdqa  (%rdi, %rcx), %xmm2
618         movdqa  %xmm2, %xmm4
620         psrldq  $4, %xmm3
621         pslldq  $12, %xmm2
622         por     %xmm3, %xmm2
624         pcmpeqb %xmm1, %xmm0
625         pcmpeqb %xmm2, %xmm1
626         psubb   %xmm0, %xmm1
627         pmovmskb %xmm1, %edx
628         sub     $0xffff, %edx
629         jnz     LABEL(exit)
631 #ifdef USE_AS_STRNCMP
632         sub     $16, %r11
633         jbe     LABEL(strcmp_exitz)
634 #endif
636         add     $16, %rcx
637         movdqa  %xmm4, %xmm3
638         jmp     LABEL(loop_ashr_4)
640         .p2align 4
641 LABEL(nibble_ashr_4):
642         pcmpeqb %xmm3, %xmm0            /* check nibble for null char */
643         pmovmskb %xmm0, %edx
644         test    $0xfff0, %edx
645         jnz     LABEL(ashr_4_exittail)
647 #ifdef USE_AS_STRNCMP
648         cmp     $11, %r11
649         jbe     LABEL(ashr_4_exittail)
650 #endif
652         pxor    %xmm0, %xmm0
653         sub     $0x1000, %r10
654         jmp     LABEL(gobble_ashr_4)
656         .p2align 4
657 LABEL(ashr_4_exittail):
658         movdqa  (%rsi, %rcx), %xmm1
659         psrldq  $4, %xmm0
660         psrldq  $4, %xmm3
661         jmp     LABEL(aftertail)
664  * The following cases will be handled by ashr_5
665  *  rcx(offset of rsi)  rax(offset of rdi)        relative offset      corresponding case
666  *        n(11~15)          n - 11                4(15 +(n-11) - n)         ashr_5
667  */
668         .p2align 4
669 LABEL(ashr_5):
670         pxor    %xmm0, %xmm0
671         movdqa  (%rdi), %xmm2
672         movdqa  (%rsi), %xmm1
673         pcmpeqb %xmm1, %xmm0
674         pslldq  $11, %xmm2
675         pcmpeqb %xmm1, %xmm2
676         psubb   %xmm0, %xmm2
677         pmovmskb %xmm2, %r9d
678         shr     %cl, %edx
679         shr     %cl, %r9d
680         sub     %r9d, %edx
681         jnz     LABEL(less32bytes)
682         movdqa  (%rdi), %xmm3
684         UPDATE_STRNCMP_COUNTER
686         pxor    %xmm0, %xmm0
687         mov     $16, %rcx       /* index for loads */
688         mov     $5, %r9d        /* byte position left over from less32bytes case */
689         /*
690          * Setup %r10 value allows us to detect crossing a page boundary.
691          * When %r10 goes positive we have crossed a page boundary and
692          * need to do a nibble.
693          */
694         lea     5(%rdi), %r10
695         and     $0xfff, %r10    /* offset into 4K page */
696         sub     $0x1000, %r10   /* subtract 4K pagesize */
698         .p2align 4
699 LABEL(loop_ashr_5):
700         add     $16, %r10
701         jg      LABEL(nibble_ashr_5)
703 LABEL(gobble_ashr_5):
704         movdqa  (%rsi, %rcx), %xmm1
705         movdqa  (%rdi, %rcx), %xmm2
706         movdqa  %xmm2, %xmm4
708         psrldq  $5, %xmm3
709         pslldq  $11, %xmm2
710         por     %xmm3, %xmm2
712         pcmpeqb %xmm1, %xmm0
713         pcmpeqb %xmm2, %xmm1
714         psubb   %xmm0, %xmm1
715         pmovmskb %xmm1, %edx
716         sub     $0xffff, %edx
717         jnz     LABEL(exit)
719 #ifdef USE_AS_STRNCMP
720         sub     $16, %r11
721         jbe     LABEL(strcmp_exitz)
722 #endif
724         add     $16, %rcx
725         movdqa  %xmm4, %xmm3
727         add     $16, %r10
728         jg      LABEL(nibble_ashr_5)    /* cross page boundary */
730         movdqa  (%rsi, %rcx), %xmm1
731         movdqa  (%rdi, %rcx), %xmm2
732         movdqa  %xmm2, %xmm4
734         psrldq  $5, %xmm3
735         pslldq  $11, %xmm2
736         por     %xmm3, %xmm2
738         pcmpeqb %xmm1, %xmm0
739         pcmpeqb %xmm2, %xmm1
740         psubb   %xmm0, %xmm1
741         pmovmskb %xmm1, %edx
742         sub     $0xffff, %edx
743         jnz     LABEL(exit)
745 #ifdef USE_AS_STRNCMP
746         sub     $16, %r11
747         jbe     LABEL(strcmp_exitz)
748 #endif
750         add     $16, %rcx
751         movdqa  %xmm4, %xmm3
752         jmp     LABEL(loop_ashr_5)
754         .p2align 4
755 LABEL(nibble_ashr_5):
756         pcmpeqb %xmm3, %xmm0            /* check nibble for null char */
757         pmovmskb %xmm0, %edx
758         test    $0xffe0, %edx
759         jnz     LABEL(ashr_5_exittail)
761 #ifdef USE_AS_STRNCMP
762         cmp     $10, %r11
763         jbe     LABEL(ashr_5_exittail)
764 #endif
766         pxor    %xmm0, %xmm0
767         sub     $0x1000, %r10
768         jmp     LABEL(gobble_ashr_5)
770         .p2align 4
771 LABEL(ashr_5_exittail):
772         movdqa  (%rsi, %rcx), %xmm1
773         psrldq  $5, %xmm0
774         psrldq  $5, %xmm3
775         jmp     LABEL(aftertail)
778  * The following cases will be handled by ashr_6
779  *  rcx(offset of rsi)  rax(offset of rdi)        relative offset      corresponding case
780  *        n(10~15)          n - 10                5(15 +(n-10) - n)         ashr_6
781  */
782         .p2align 4
783 LABEL(ashr_6):
784         pxor    %xmm0, %xmm0
785         movdqa  (%rdi), %xmm2
786         movdqa  (%rsi), %xmm1
787         pcmpeqb %xmm1, %xmm0
788         pslldq  $10, %xmm2
789         pcmpeqb %xmm1, %xmm2
790         psubb   %xmm0, %xmm2
791         pmovmskb %xmm2, %r9d
792         shr     %cl, %edx
793         shr     %cl, %r9d
794         sub     %r9d, %edx
795         jnz     LABEL(less32bytes)
796         movdqa  (%rdi), %xmm3
798         UPDATE_STRNCMP_COUNTER
800         pxor    %xmm0, %xmm0
801         mov     $16, %rcx       /* index for loads */
802         mov     $6, %r9d        /* byte position left over from less32bytes case */
803         /*
804          * Setup %r10 value allows us to detect crossing a page boundary.
805          * When %r10 goes positive we have crossed a page boundary and
806          * need to do a nibble.
807          */
808         lea     6(%rdi), %r10
809         and     $0xfff, %r10    /* offset into 4K page */
810         sub     $0x1000, %r10   /* subtract 4K pagesize */
812         .p2align 4
813 LABEL(loop_ashr_6):
814         add     $16, %r10
815         jg      LABEL(nibble_ashr_6)
817 LABEL(gobble_ashr_6):
818         movdqa  (%rsi, %rcx), %xmm1
819         movdqa  (%rdi, %rcx), %xmm2
820         movdqa  %xmm2, %xmm4
822         psrldq  $6, %xmm3
823         pslldq  $10, %xmm2
824         por     %xmm3, %xmm2
826         pcmpeqb %xmm1, %xmm0
827         pcmpeqb %xmm2, %xmm1
828         psubb   %xmm0, %xmm1
829         pmovmskb %xmm1, %edx
830         sub     $0xffff, %edx
831         jnz     LABEL(exit)
833 #ifdef USE_AS_STRNCMP
834         sub     $16, %r11
835         jbe     LABEL(strcmp_exitz)
836 #endif
838         add     $16, %rcx
839         movdqa  %xmm4, %xmm3
841         add     $16, %r10
842         jg      LABEL(nibble_ashr_6)    /* cross page boundary */
844         movdqa  (%rsi, %rcx), %xmm1
845         movdqa  (%rdi, %rcx), %xmm2
846         movdqa  %xmm2, %xmm4
848         psrldq  $6, %xmm3
849         pslldq  $10, %xmm2
850         por     %xmm3, %xmm2
852         pcmpeqb %xmm1, %xmm0
853         pcmpeqb %xmm2, %xmm1
854         psubb   %xmm0, %xmm1
855         pmovmskb %xmm1, %edx
856         sub     $0xffff, %edx
857         jnz     LABEL(exit)
859 #ifdef USE_AS_STRNCMP
860         sub     $16, %r11
861         jbe     LABEL(strcmp_exitz)
862 #endif
864         add     $16, %rcx
865         movdqa  %xmm4, %xmm3
866         jmp     LABEL(loop_ashr_6)
868         .p2align 4
869 LABEL(nibble_ashr_6):
870         pcmpeqb %xmm3, %xmm0            /* check nibble for null char */
871         pmovmskb %xmm0, %edx
872         test    $0xffc0, %edx
873         jnz     LABEL(ashr_6_exittail)
875 #ifdef USE_AS_STRNCMP
876         cmp     $9, %r11
877         jbe     LABEL(ashr_6_exittail)
878 #endif
880         pxor    %xmm0, %xmm0
881         sub     $0x1000, %r10
882         jmp     LABEL(gobble_ashr_6)
884         .p2align 4
885 LABEL(ashr_6_exittail):
886         movdqa  (%rsi, %rcx), %xmm1
887         psrldq  $6, %xmm0
888         psrldq  $6, %xmm3
889         jmp     LABEL(aftertail)
892  * The following cases will be handled by ashr_7
893  *  rcx(offset of rsi)  rax(offset of rdi)        relative offset      corresponding case
894  *        n(9~15)          n - 9                6(15 +(n - 9) - n)         ashr_7
895  */
896         .p2align 4
897 LABEL(ashr_7):
898         pxor    %xmm0, %xmm0
899         movdqa  (%rdi), %xmm2
900         movdqa  (%rsi), %xmm1
901         pcmpeqb %xmm1, %xmm0
902         pslldq  $9, %xmm2
903         pcmpeqb %xmm1, %xmm2
904         psubb   %xmm0, %xmm2
905         pmovmskb %xmm2, %r9d
906         shr     %cl, %edx
907         shr     %cl, %r9d
908         sub     %r9d, %edx
909         jnz     LABEL(less32bytes)
910         movdqa  (%rdi), %xmm3
912         UPDATE_STRNCMP_COUNTER
914         pxor    %xmm0, %xmm0
915         mov     $16, %rcx       /* index for loads */
916         mov     $7, %r9d        /* byte position left over from less32bytes case */
917         /*
918          * Setup %r10 value allows us to detect crossing a page boundary.
919          * When %r10 goes positive we have crossed a page boundary and
920          * need to do a nibble.
921          */
922         lea     7(%rdi), %r10
923         and     $0xfff, %r10    /* offset into 4K page */
924         sub     $0x1000, %r10   /* subtract 4K pagesize */
926         .p2align 4
927 LABEL(loop_ashr_7):
928         add     $16, %r10
929         jg      LABEL(nibble_ashr_7)
931 LABEL(gobble_ashr_7):
932         movdqa  (%rsi, %rcx), %xmm1
933         movdqa  (%rdi, %rcx), %xmm2
934         movdqa  %xmm2, %xmm4
936         psrldq  $7, %xmm3
937         pslldq  $9, %xmm2
938         por     %xmm3, %xmm2
940         pcmpeqb %xmm1, %xmm0
941         pcmpeqb %xmm2, %xmm1
942         psubb   %xmm0, %xmm1
943         pmovmskb %xmm1, %edx
944         sub     $0xffff, %edx
945         jnz     LABEL(exit)
947 #ifdef USE_AS_STRNCMP
948         sub     $16, %r11
949         jbe     LABEL(strcmp_exitz)
950 #endif
952         add     $16, %rcx
953         movdqa  %xmm4, %xmm3
955         add     $16, %r10
956         jg      LABEL(nibble_ashr_7)    /* cross page boundary */
958         movdqa  (%rsi, %rcx), %xmm1
959         movdqa  (%rdi, %rcx), %xmm2
960         movdqa  %xmm2, %xmm4
962         psrldq  $7, %xmm3
963         pslldq  $9, %xmm2
964         por     %xmm3, %xmm2
966         pcmpeqb %xmm1, %xmm0
967         pcmpeqb %xmm2, %xmm1
968         psubb   %xmm0, %xmm1
969         pmovmskb %xmm1, %edx
970         sub     $0xffff, %edx
971         jnz     LABEL(exit)
973 #ifdef USE_AS_STRNCMP
974         sub     $16, %r11
975         jbe     LABEL(strcmp_exitz)
976 #endif
978         add     $16, %rcx
979         movdqa  %xmm4, %xmm3
980         jmp     LABEL(loop_ashr_7)
982         .p2align 4
983 LABEL(nibble_ashr_7):
984         pcmpeqb %xmm3, %xmm0            /* check nibble for null char */
985         pmovmskb %xmm0, %edx
986         test    $0xff80, %edx
987         jnz     LABEL(ashr_7_exittail)
989 #ifdef USE_AS_STRNCMP
990         cmp     $8, %r11
991         jbe     LABEL(ashr_7_exittail)
992 #endif
994         pxor    %xmm0, %xmm0
995         sub     $0x1000, %r10
996         jmp     LABEL(gobble_ashr_7)
998         .p2align 4
999 LABEL(ashr_7_exittail):
1000         movdqa  (%rsi, %rcx), %xmm1
1001         psrldq  $7, %xmm0
1002         psrldq  $7, %xmm3
1003         jmp     LABEL(aftertail)
1006  *  The following cases will be handled by ashr_8
1007  *  rcx(offset of rsi)  rax(offset of rdi)        relative offset        corresponding case
1008  *        n(8~15)          n - 8                7(15 +(n - 8) - n)         ashr_8
1009  */
1010         .p2align 4
1011 LABEL(ashr_8):
1012         pxor    %xmm0, %xmm0
1013         movdqa  (%rdi), %xmm2
1014         movdqa  (%rsi), %xmm1
1015         pcmpeqb %xmm1, %xmm0
1016         pslldq  $8, %xmm2
1017         pcmpeqb %xmm1, %xmm2
1018         psubb   %xmm0, %xmm2
1019         pmovmskb %xmm2, %r9d
1020         shr     %cl, %edx
1021         shr     %cl, %r9d
1022         sub     %r9d, %edx
1023         jnz     LABEL(less32bytes)
1024         movdqa  (%rdi), %xmm3
1026         UPDATE_STRNCMP_COUNTER
1028         pxor    %xmm0, %xmm0
1029         mov     $16, %rcx       /* index for loads */
1030         mov     $8, %r9d        /* byte position left over from less32bytes case */
1031         /*
1032          * Setup %r10 value allows us to detect crossing a page boundary.
1033          * When %r10 goes positive we have crossed a page boundary and
1034          * need to do a nibble.
1035          */
1036         lea     8(%rdi), %r10
1037         and     $0xfff, %r10    /* offset into 4K page */
1038         sub     $0x1000, %r10   /* subtract 4K pagesize */
1040         .p2align 4
1041 LABEL(loop_ashr_8):
1042         add     $16, %r10
1043         jg      LABEL(nibble_ashr_8)
1045 LABEL(gobble_ashr_8):
1046         movdqa  (%rsi, %rcx), %xmm1
1047         movdqa  (%rdi, %rcx), %xmm2
1048         movdqa  %xmm2, %xmm4
1050         psrldq  $8, %xmm3
1051         pslldq  $8, %xmm2
1052         por     %xmm3, %xmm2
1054         pcmpeqb %xmm1, %xmm0
1055         pcmpeqb %xmm2, %xmm1
1056         psubb   %xmm0, %xmm1
1057         pmovmskb %xmm1, %edx
1058         sub     $0xffff, %edx
1059         jnz     LABEL(exit)
1061 #ifdef USE_AS_STRNCMP
1062         sub     $16, %r11
1063         jbe     LABEL(strcmp_exitz)
1064 #endif
1066         add     $16, %rcx
1067         movdqa  %xmm4, %xmm3
1069         add     $16, %r10
1070         jg      LABEL(nibble_ashr_8)    /* cross page boundary */
1072         movdqa  (%rsi, %rcx), %xmm1
1073         movdqa  (%rdi, %rcx), %xmm2
1074         movdqa  %xmm2, %xmm4
1076         psrldq  $8, %xmm3
1077         pslldq  $8, %xmm2
1078         por     %xmm3, %xmm2
1080         pcmpeqb %xmm1, %xmm0
1081         pcmpeqb %xmm2, %xmm1
1082         psubb   %xmm0, %xmm1
1083         pmovmskb %xmm1, %edx
1084         sub     $0xffff, %edx
1085         jnz     LABEL(exit)
1087 #ifdef USE_AS_STRNCMP
1088         sub     $16, %r11
1089         jbe     LABEL(strcmp_exitz)
1090 #endif
1092         add     $16, %rcx
1093         movdqa  %xmm4, %xmm3
1094         jmp     LABEL(loop_ashr_8)
1096         .p2align 4
1097 LABEL(nibble_ashr_8):
1098         pcmpeqb %xmm3, %xmm0            /* check nibble for null char */
1099         pmovmskb %xmm0, %edx
1100         test    $0xff00, %edx
1101         jnz     LABEL(ashr_8_exittail)
1103 #ifdef USE_AS_STRNCMP
1104         cmp     $7, %r11
1105         jbe     LABEL(ashr_8_exittail)
1106 #endif
1108         pxor    %xmm0, %xmm0
1109         sub     $0x1000, %r10
1110         jmp     LABEL(gobble_ashr_8)
1112         .p2align 4
1113 LABEL(ashr_8_exittail):
1114         movdqa  (%rsi, %rcx), %xmm1
1115         psrldq  $8, %xmm0
1116         psrldq  $8, %xmm3
1117         jmp     LABEL(aftertail)
1120  *  The following cases will be handled by ashr_9
1121  *  rcx(offset of rsi)  rax(offset of rdi)        relative offset        corresponding case
1122  *        n(7~15)          n - 7                8(15 +(n - 7) - n)         ashr_9
1123  */
1124         .p2align 4
1125 LABEL(ashr_9):
1126         pxor    %xmm0, %xmm0
1127         movdqa  (%rdi), %xmm2
1128         movdqa  (%rsi), %xmm1
1129         pcmpeqb %xmm1, %xmm0
1130         pslldq  $7, %xmm2
1131         pcmpeqb %xmm1, %xmm2
1132         psubb   %xmm0, %xmm2
1133         pmovmskb %xmm2, %r9d
1134         shr     %cl, %edx
1135         shr     %cl, %r9d
1136         sub     %r9d, %edx
1137         jnz     LABEL(less32bytes)
1138         movdqa  (%rdi), %xmm3
1140         UPDATE_STRNCMP_COUNTER
1142         pxor    %xmm0, %xmm0
1143         mov     $16, %rcx       /* index for loads */
1144         mov     $9, %r9d        /* byte position left over from less32bytes case */
1145         /*
1146          * Setup %r10 value allows us to detect crossing a page boundary.
1147          * When %r10 goes positive we have crossed a page boundary and
1148          * need to do a nibble.
1149          */
1150         lea     9(%rdi), %r10
1151         and     $0xfff, %r10    /* offset into 4K page */
1152         sub     $0x1000, %r10   /* subtract 4K pagesize */
1154         .p2align 4
1155 LABEL(loop_ashr_9):
1156         add     $16, %r10
1157         jg      LABEL(nibble_ashr_9)
1159 LABEL(gobble_ashr_9):
1160         movdqa  (%rsi, %rcx), %xmm1
1161         movdqa  (%rdi, %rcx), %xmm2
1162         movdqa  %xmm2, %xmm4
1164         psrldq  $9, %xmm3
1165         pslldq  $7, %xmm2
1166         por     %xmm3, %xmm2
1168         pcmpeqb %xmm1, %xmm0
1169         pcmpeqb %xmm2, %xmm1
1170         psubb   %xmm0, %xmm1
1171         pmovmskb %xmm1, %edx
1172         sub     $0xffff, %edx
1173         jnz     LABEL(exit)
1175 #ifdef USE_AS_STRNCMP
1176         sub     $16, %r11
1177         jbe     LABEL(strcmp_exitz)
1178 #endif
1180         add     $16, %rcx
1181         movdqa  %xmm4, %xmm3
1183         add     $16, %r10
1184         jg      LABEL(nibble_ashr_9)    /* cross page boundary */
1186         movdqa  (%rsi, %rcx), %xmm1
1187         movdqa  (%rdi, %rcx), %xmm2
1188         movdqa  %xmm2, %xmm4
1190         psrldq  $9, %xmm3
1191         pslldq  $7, %xmm2
1192         por     %xmm3, %xmm2
1194         pcmpeqb %xmm1, %xmm0
1195         pcmpeqb %xmm2, %xmm1
1196         psubb   %xmm0, %xmm1
1197         pmovmskb %xmm1, %edx
1198         sub     $0xffff, %edx
1199         jnz     LABEL(exit)
1201 #ifdef USE_AS_STRNCMP
1202         sub     $16, %r11
1203         jbe     LABEL(strcmp_exitz)
1204 #endif
1206         add     $16, %rcx
1207         movdqa  %xmm4, %xmm3            /* store for next cycle */
1208         jmp     LABEL(loop_ashr_9)
1210         .p2align 4
1211 LABEL(nibble_ashr_9):
1212         pcmpeqb %xmm3, %xmm0            /* check nibble for null char */
1213         pmovmskb %xmm0, %edx
1214         test    $0xfe00, %edx
1215         jnz     LABEL(ashr_9_exittail)
1217 #ifdef USE_AS_STRNCMP
1218         cmp     $6, %r11
1219         jbe     LABEL(ashr_9_exittail)
1220 #endif
1222         pxor    %xmm0, %xmm0
1223         sub     $0x1000, %r10
1224         jmp     LABEL(gobble_ashr_9)
1226         .p2align 4
1227 LABEL(ashr_9_exittail):
1228         movdqa  (%rsi, %rcx), %xmm1
1229         psrldq  $9, %xmm0
1230         psrldq  $9, %xmm3
1231         jmp     LABEL(aftertail)
1234  *  The following cases will be handled by ashr_10
1235  *  rcx(offset of rsi)  rax(offset of rdi)        relative offset        corresponding case
1236  *        n(6~15)          n - 6                9(15 +(n - 6) - n)         ashr_10
1237  */
1238         .p2align 4
1239 LABEL(ashr_10):
1240         pxor    %xmm0, %xmm0
1241         movdqa  (%rdi), %xmm2
1242         movdqa  (%rsi), %xmm1
1243         pcmpeqb %xmm1, %xmm0
1244         pslldq  $6, %xmm2
1245         pcmpeqb %xmm1, %xmm2
1246         psubb   %xmm0, %xmm2
1247         pmovmskb %xmm2, %r9d
1248         shr     %cl, %edx
1249         shr     %cl, %r9d
1250         sub     %r9d, %edx
1251         jnz     LABEL(less32bytes)
1252         movdqa  (%rdi), %xmm3
1254         UPDATE_STRNCMP_COUNTER
1256         pxor    %xmm0, %xmm0
1257         mov     $16, %rcx       /* index for loads */
1258         mov     $10, %r9d       /* byte position left over from less32bytes case */
1259         /*
1260          * Setup %r10 value allows us to detect crossing a page boundary.
1261          * When %r10 goes positive we have crossed a page boundary and
1262          * need to do a nibble.
1263          */
1264         lea     10(%rdi), %r10
1265         and     $0xfff, %r10    /* offset into 4K page */
1266         sub     $0x1000, %r10   /* subtract 4K pagesize */
1268         .p2align 4
1269 LABEL(loop_ashr_10):
1270         add     $16, %r10
1271         jg      LABEL(nibble_ashr_10)
1273 LABEL(gobble_ashr_10):
1274         movdqa  (%rsi, %rcx), %xmm1
1275         movdqa  (%rdi, %rcx), %xmm2
1276         movdqa  %xmm2, %xmm4
1278         psrldq  $10, %xmm3
1279         pslldq  $6, %xmm2
1280         por     %xmm3, %xmm2
1282         pcmpeqb %xmm1, %xmm0
1283         pcmpeqb %xmm2, %xmm1
1284         psubb   %xmm0, %xmm1
1285         pmovmskb %xmm1, %edx
1286         sub     $0xffff, %edx
1287         jnz     LABEL(exit)
1289 #ifdef USE_AS_STRNCMP
1290         sub     $16, %r11
1291         jbe     LABEL(strcmp_exitz)
1292 #endif
1294         add     $16, %rcx
1295         movdqa  %xmm4, %xmm3
1297         add     $16, %r10
1298         jg      LABEL(nibble_ashr_10)   /* cross page boundary */
1300         movdqa  (%rsi, %rcx), %xmm1
1301         movdqa  (%rdi, %rcx), %xmm2
1302         movdqa  %xmm2, %xmm4
1304         psrldq  $10, %xmm3
1305         pslldq  $6, %xmm2
1306         por     %xmm3, %xmm2
1308         pcmpeqb %xmm1, %xmm0
1309         pcmpeqb %xmm2, %xmm1
1310         psubb   %xmm0, %xmm1
1311         pmovmskb %xmm1, %edx
1312         sub     $0xffff, %edx
1313         jnz     LABEL(exit)
1315 #ifdef USE_AS_STRNCMP
1316         sub     $16, %r11
1317         jbe     LABEL(strcmp_exitz)
1318 #endif
1320         add     $16, %rcx
1321         movdqa  %xmm4, %xmm3
1322         jmp     LABEL(loop_ashr_10)
1324         .p2align 4
1325 LABEL(nibble_ashr_10):
1326         pcmpeqb %xmm3, %xmm0            /* check nibble for null char */
1327         pmovmskb %xmm0, %edx
1328         test    $0xfc00, %edx
1329         jnz     LABEL(ashr_10_exittail)
1331 #ifdef USE_AS_STRNCMP
1332         cmp     $5, %r11
1333         jbe     LABEL(ashr_10_exittail)
1334 #endif
1336         pxor    %xmm0, %xmm0
1337         sub     $0x1000, %r10
1338         jmp     LABEL(gobble_ashr_10)
1340         .p2align 4
1341 LABEL(ashr_10_exittail):
1342         movdqa  (%rsi, %rcx), %xmm1
1343         psrldq  $10, %xmm0
1344         psrldq  $10, %xmm3
1345         jmp     LABEL(aftertail)
1348  *  The following cases will be handled by ashr_11
1349  *  rcx(offset of rsi)  rax(offset of rdi)        relative offset        corresponding case
1350  *        n(5~15)          n - 5                10(15 +(n - 5) - n)         ashr_11
1351  */
1352         .p2align 4
1353 LABEL(ashr_11):
1354         pxor    %xmm0, %xmm0
1355         movdqa  (%rdi), %xmm2
1356         movdqa  (%rsi), %xmm1
1357         pcmpeqb %xmm1, %xmm0
1358         pslldq  $5, %xmm2
1359         pcmpeqb %xmm1, %xmm2
1360         psubb   %xmm0, %xmm2
1361         pmovmskb %xmm2, %r9d
1362         shr     %cl, %edx
1363         shr     %cl, %r9d
1364         sub     %r9d, %edx
1365         jnz     LABEL(less32bytes)
1366         movdqa  (%rdi), %xmm3
1368         UPDATE_STRNCMP_COUNTER
1370         pxor    %xmm0, %xmm0
1371         mov     $16, %rcx       /* index for loads */
1372         mov     $11, %r9d       /* byte position left over from less32bytes case */
1373         /*
1374          * Setup %r10 value allows us to detect crossing a page boundary.
1375          * When %r10 goes positive we have crossed a page boundary and
1376          * need to do a nibble.
1377          */
1378         lea     11(%rdi), %r10
1379         and     $0xfff, %r10    /* offset into 4K page */
1380         sub     $0x1000, %r10   /* subtract 4K pagesize */
1382         .p2align 4
1383 LABEL(loop_ashr_11):
1384         add     $16, %r10
1385         jg      LABEL(nibble_ashr_11)
1387 LABEL(gobble_ashr_11):
1388         movdqa  (%rsi, %rcx), %xmm1
1389         movdqa  (%rdi, %rcx), %xmm2
1390         movdqa  %xmm2, %xmm4
1392         psrldq  $11, %xmm3
1393         pslldq  $5, %xmm2
1394         por     %xmm3, %xmm2
1396         pcmpeqb %xmm1, %xmm0
1397         pcmpeqb %xmm2, %xmm1
1398         psubb   %xmm0, %xmm1
1399         pmovmskb %xmm1, %edx
1400         sub     $0xffff, %edx
1401         jnz     LABEL(exit)
1403 #ifdef USE_AS_STRNCMP
1404         sub     $16, %r11
1405         jbe     LABEL(strcmp_exitz)
1406 #endif
1408         add     $16, %rcx
1409         movdqa  %xmm4, %xmm3
1411         add     $16, %r10
1412         jg      LABEL(nibble_ashr_11)   /* cross page boundary */
1414         movdqa  (%rsi, %rcx), %xmm1
1415         movdqa  (%rdi, %rcx), %xmm2
1416         movdqa  %xmm2, %xmm4
1418         psrldq  $11, %xmm3
1419         pslldq  $5, %xmm2
1420         por     %xmm3, %xmm2
1422         pcmpeqb %xmm1, %xmm0
1423         pcmpeqb %xmm2, %xmm1
1424         psubb   %xmm0, %xmm1
1425         pmovmskb %xmm1, %edx
1426         sub     $0xffff, %edx
1427         jnz     LABEL(exit)
1429 #ifdef USE_AS_STRNCMP
1430         sub     $16, %r11
1431         jbe     LABEL(strcmp_exitz)
1432 #endif
1434         add     $16, %rcx
1435         movdqa  %xmm4, %xmm3
1436         jmp     LABEL(loop_ashr_11)
1438         .p2align 4
1439 LABEL(nibble_ashr_11):
1440         pcmpeqb %xmm3, %xmm0            /* check nibble for null char */
1441         pmovmskb %xmm0, %edx
1442         test    $0xf800, %edx
1443         jnz     LABEL(ashr_11_exittail)
1445 #ifdef USE_AS_STRNCMP
1446         cmp     $4, %r11
1447         jbe     LABEL(ashr_11_exittail)
1448 #endif
1450         pxor    %xmm0, %xmm0
1451         sub     $0x1000, %r10
1452         jmp     LABEL(gobble_ashr_11)
1454         .p2align 4
1455 LABEL(ashr_11_exittail):
1456         movdqa  (%rsi, %rcx), %xmm1
1457         psrldq  $11, %xmm0
1458         psrldq  $11, %xmm3
1459         jmp     LABEL(aftertail)
1462  *  The following cases will be handled by ashr_12
1463  *  rcx(offset of rsi)  rax(offset of rdi)        relative offset        corresponding case
1464  *        n(4~15)          n - 4                11(15 +(n - 4) - n)         ashr_12
1465  */
1466         .p2align 4
1467 LABEL(ashr_12):
1468         pxor    %xmm0, %xmm0
1469         movdqa  (%rdi), %xmm2
1470         movdqa  (%rsi), %xmm1
1471         pcmpeqb %xmm1, %xmm0
1472         pslldq  $4, %xmm2
1473         pcmpeqb %xmm1, %xmm2
1474         psubb   %xmm0, %xmm2
1475         pmovmskb %xmm2, %r9d
1476         shr     %cl, %edx
1477         shr     %cl, %r9d
1478         sub     %r9d, %edx
1479         jnz     LABEL(less32bytes)
1480         movdqa  (%rdi), %xmm3
1482         UPDATE_STRNCMP_COUNTER
1484         pxor    %xmm0, %xmm0
1485         mov     $16, %rcx       /* index for loads */
1486         mov     $12, %r9d       /* byte position left over from less32bytes case */
1487         /*
1488          * Setup %r10 value allows us to detect crossing a page boundary.
1489          * When %r10 goes positive we have crossed a page boundary and
1490          * need to do a nibble.
1491          */
1492         lea     12(%rdi), %r10
1493         and     $0xfff, %r10    /* offset into 4K page */
1494         sub     $0x1000, %r10   /* subtract 4K pagesize */
1496         .p2align 4
1497 LABEL(loop_ashr_12):
1498         add     $16, %r10
1499         jg      LABEL(nibble_ashr_12)
1501 LABEL(gobble_ashr_12):
1502         movdqa  (%rsi, %rcx), %xmm1
1503         movdqa  (%rdi, %rcx), %xmm2
1504         movdqa  %xmm2, %xmm4
1506         psrldq  $12, %xmm3
1507         pslldq  $4, %xmm2
1508         por     %xmm3, %xmm2
1510         pcmpeqb %xmm1, %xmm0
1511         pcmpeqb %xmm2, %xmm1
1512         psubb   %xmm0, %xmm1
1513         pmovmskb %xmm1, %edx
1514         sub     $0xffff, %edx
1515         jnz     LABEL(exit)
1517 #ifdef USE_AS_STRNCMP
1518         sub     $16, %r11
1519         jbe     LABEL(strcmp_exitz)
1520 #endif
1522         add     $16, %rcx
1523         movdqa  %xmm4, %xmm3
1525         add     $16, %r10
1526         jg      LABEL(nibble_ashr_12)   /* cross page boundary */
1528         movdqa  (%rsi, %rcx), %xmm1
1529         movdqa  (%rdi, %rcx), %xmm2
1530         movdqa  %xmm2, %xmm4
1532         psrldq  $12, %xmm3
1533         pslldq  $4, %xmm2
1534         por     %xmm3, %xmm2
1536         pcmpeqb %xmm1, %xmm0
1537         pcmpeqb %xmm2, %xmm1
1538         psubb   %xmm0, %xmm1
1539         pmovmskb %xmm1, %edx
1540         sub     $0xffff, %edx
1541         jnz     LABEL(exit)
1543 #ifdef USE_AS_STRNCMP
1544         sub     $16, %r11
1545         jbe     LABEL(strcmp_exitz)
1546 #endif
1548         add     $16, %rcx
1549         movdqa  %xmm4, %xmm3
1550         jmp     LABEL(loop_ashr_12)
1552         .p2align 4
1553 LABEL(nibble_ashr_12):
1554         pcmpeqb %xmm3, %xmm0            /* check nibble for null char */
1555         pmovmskb %xmm0, %edx
1556         test    $0xf000, %edx
1557         jnz     LABEL(ashr_12_exittail)
1559 #ifdef USE_AS_STRNCMP
1560         cmp     $3, %r11
1561         jbe     LABEL(ashr_12_exittail)
1562 #endif
1564         pxor    %xmm0, %xmm0
1565         sub     $0x1000, %r10
1566         jmp     LABEL(gobble_ashr_12)
1568         .p2align 4
1569 LABEL(ashr_12_exittail):
1570         movdqa  (%rsi, %rcx), %xmm1
1571         psrldq  $12, %xmm0
1572         psrldq  $12, %xmm3
1573         jmp     LABEL(aftertail)
1576  *  The following cases will be handled by ashr_13
1577  *  rcx(offset of rsi)  rax(offset of rdi)        relative offset        corresponding case
1578  *        n(3~15)          n - 3                12(15 +(n - 3) - n)         ashr_13
1579  */
1580         .p2align 4
1581 LABEL(ashr_13):
1582         pxor    %xmm0, %xmm0
1583         movdqa  (%rdi), %xmm2
1584         movdqa  (%rsi), %xmm1
1585         pcmpeqb %xmm1, %xmm0
1586         pslldq  $3, %xmm2
1587         pcmpeqb %xmm1, %xmm2
1588         psubb   %xmm0, %xmm2
1589         pmovmskb %xmm2, %r9d
1590         shr     %cl, %edx
1591         shr     %cl, %r9d
1592         sub     %r9d, %edx
1593         jnz     LABEL(less32bytes)
1594         movdqa  (%rdi), %xmm3
1596         UPDATE_STRNCMP_COUNTER
1598         pxor    %xmm0, %xmm0
1599         mov     $16, %rcx       /* index for loads */
1600         mov     $13, %r9d       /* byte position left over from less32bytes case */
1601         /*
1602          * Setup %r10 value allows us to detect crossing a page boundary.
1603          * When %r10 goes positive we have crossed a page boundary and
1604          * need to do a nibble.
1605          */
1606         lea     13(%rdi), %r10
1607         and     $0xfff, %r10    /* offset into 4K page */
1608         sub     $0x1000, %r10   /* subtract 4K pagesize */
1610         .p2align 4
1611 LABEL(loop_ashr_13):
1612         add     $16, %r10
1613         jg      LABEL(nibble_ashr_13)
1615 LABEL(gobble_ashr_13):
1616         movdqa  (%rsi, %rcx), %xmm1
1617         movdqa  (%rdi, %rcx), %xmm2
1618         movdqa  %xmm2, %xmm4
1620         psrldq  $13, %xmm3
1621         pslldq  $3, %xmm2
1622         por     %xmm3, %xmm2
1624         pcmpeqb %xmm1, %xmm0
1625         pcmpeqb %xmm2, %xmm1
1626         psubb   %xmm0, %xmm1
1627         pmovmskb %xmm1, %edx
1628         sub     $0xffff, %edx
1629         jnz     LABEL(exit)
1631 #ifdef USE_AS_STRNCMP
1632         sub     $16, %r11
1633         jbe     LABEL(strcmp_exitz)
1634 #endif
1636         add     $16, %rcx
1637         movdqa  %xmm4, %xmm3
1639         add     $16, %r10
1640         jg      LABEL(nibble_ashr_13)   /* cross page boundary */
1642         movdqa  (%rsi, %rcx), %xmm1
1643         movdqa  (%rdi, %rcx), %xmm2
1644         movdqa  %xmm2, %xmm4
1646         psrldq  $13, %xmm3
1647         pslldq  $3, %xmm2
1648         por     %xmm3, %xmm2
1650         pcmpeqb %xmm1, %xmm0
1651         pcmpeqb %xmm2, %xmm1
1652         psubb   %xmm0, %xmm1
1653         pmovmskb %xmm1, %edx
1654         sub     $0xffff, %edx
1655         jnz     LABEL(exit)
1657 #ifdef USE_AS_STRNCMP
1658         sub     $16, %r11
1659         jbe     LABEL(strcmp_exitz)
1660 #endif
1662         add     $16, %rcx
1663         movdqa  %xmm4, %xmm3
1664         jmp     LABEL(loop_ashr_13)
1666         .p2align 4
1667 LABEL(nibble_ashr_13):
1668         pcmpeqb %xmm3, %xmm0            /* check nibble for null char */
1669         pmovmskb %xmm0, %edx
1670         test    $0xe000, %edx
1671         jnz     LABEL(ashr_13_exittail)
1673 #ifdef USE_AS_STRNCMP
1674         cmp     $2, %r11
1675         jbe     LABEL(ashr_13_exittail)
1676 #endif
1678         pxor    %xmm0, %xmm0
1679         sub     $0x1000, %r10
1680         jmp     LABEL(gobble_ashr_13)
1682         .p2align 4
1683 LABEL(ashr_13_exittail):
1684         movdqa  (%rsi, %rcx), %xmm1
1685         psrldq  $13, %xmm0
1686         psrldq  $13, %xmm3
1687         jmp     LABEL(aftertail)
1690  *  The following cases will be handled by ashr_14
1691  *  rcx(offset of rsi)  rax(offset of rdi)        relative offset        corresponding case
1692  *        n(2~15)          n - 2                13(15 +(n - 2) - n)         ashr_14
1693  */
1694         .p2align 4
1695 LABEL(ashr_14):
1696         pxor    %xmm0, %xmm0
1697         movdqa  (%rdi), %xmm2
1698         movdqa  (%rsi), %xmm1
1699         pcmpeqb %xmm1, %xmm0
1700         pslldq  $2, %xmm2
1701         pcmpeqb %xmm1, %xmm2
1702         psubb   %xmm0, %xmm2
1703         pmovmskb %xmm2, %r9d
1704         shr     %cl, %edx
1705         shr     %cl, %r9d
1706         sub     %r9d, %edx
1707         jnz     LABEL(less32bytes)
1708         movdqa  (%rdi), %xmm3
1710         UPDATE_STRNCMP_COUNTER
1712         pxor    %xmm0, %xmm0
1713         mov     $16, %rcx       /* index for loads */
1714         mov     $14, %r9d       /* byte position left over from less32bytes case */
1715         /*
1716          * Setup %r10 value allows us to detect crossing a page boundary.
1717          * When %r10 goes positive we have crossed a page boundary and
1718          * need to do a nibble.
1719          */
1720         lea     14(%rdi), %r10
1721         and     $0xfff, %r10    /* offset into 4K page */
1722         sub     $0x1000, %r10   /* subtract 4K pagesize */
1724         .p2align 4
1725 LABEL(loop_ashr_14):
1726         add     $16, %r10
1727         jg      LABEL(nibble_ashr_14)
1729 LABEL(gobble_ashr_14):
1730         movdqa  (%rsi, %rcx), %xmm1
1731         movdqa  (%rdi, %rcx), %xmm2
1732         movdqa  %xmm2, %xmm4
1734         psrldq  $14, %xmm3
1735         pslldq  $2, %xmm2
1736         por     %xmm3, %xmm2
1738         pcmpeqb %xmm1, %xmm0
1739         pcmpeqb %xmm2, %xmm1
1740         psubb   %xmm0, %xmm1
1741         pmovmskb %xmm1, %edx
1742         sub     $0xffff, %edx
1743         jnz     LABEL(exit)
1745 #ifdef USE_AS_STRNCMP
1746         sub     $16, %r11
1747         jbe     LABEL(strcmp_exitz)
1748 #endif
1750         add     $16, %rcx
1751         movdqa  %xmm4, %xmm3
1753         add     $16, %r10
1754         jg      LABEL(nibble_ashr_14)   /* cross page boundary */
1756         movdqa  (%rsi, %rcx), %xmm1
1757         movdqa  (%rdi, %rcx), %xmm2
1758         movdqa  %xmm2, %xmm4
1760         psrldq  $14, %xmm3
1761         pslldq  $2, %xmm2
1762         por     %xmm3, %xmm2
1764         pcmpeqb %xmm1, %xmm0
1765         pcmpeqb %xmm2, %xmm1
1766         psubb   %xmm0, %xmm1
1767         pmovmskb %xmm1, %edx
1768         sub     $0xffff, %edx
1769         jnz     LABEL(exit)
1771 #ifdef USE_AS_STRNCMP
1772         sub     $16, %r11
1773         jbe     LABEL(strcmp_exitz)
1774 #endif
1776         add     $16, %rcx
1777         movdqa  %xmm4, %xmm3
1778         jmp     LABEL(loop_ashr_14)
1780         .p2align 4
1781 LABEL(nibble_ashr_14):
1782         pcmpeqb %xmm3, %xmm0            /* check nibble for null char */
1783         pmovmskb %xmm0, %edx
1784         test    $0xc000, %edx
1785         jnz     LABEL(ashr_14_exittail)
1787 #ifdef USE_AS_STRNCMP
1788         cmp     $1, %r11
1789         jbe     LABEL(ashr_14_exittail)
1790 #endif
1792         pxor    %xmm0, %xmm0
1793         sub     $0x1000, %r10
1794         jmp     LABEL(gobble_ashr_14)
1796         .p2align 4
1797 LABEL(ashr_14_exittail):
1798         movdqa  (%rsi, %rcx), %xmm1
1799         psrldq  $14, %xmm0
1800         psrldq  $14, %xmm3
1801         jmp     LABEL(aftertail)
1804  *  The following cases will be handled by ashr_15
1805  *  rcx(offset of rsi)  rax(offset of rdi)        relative offset        corresponding case
1806  *        n(1~15)          n - 1                14(15 +(n - 1) - n)         ashr_15
1807  */
1808         .p2align 4
1809 LABEL(ashr_15):
1810         pxor    %xmm0, %xmm0
1811         movdqa  (%rdi), %xmm2
1812         movdqa  (%rsi), %xmm1
1813         pcmpeqb %xmm1, %xmm0
1814         pslldq  $1, %xmm2
1815         pcmpeqb %xmm1, %xmm2
1816         psubb   %xmm0, %xmm2
1817         pmovmskb %xmm2, %r9d
1818         shr     %cl, %edx
1819         shr     %cl, %r9d
1820         sub     %r9d, %edx
1821         jnz     LABEL(less32bytes)
1823         movdqa  (%rdi), %xmm3
1825         UPDATE_STRNCMP_COUNTER
1827         pxor    %xmm0, %xmm0
1828         mov     $16, %rcx       /* index for loads */
1829         mov     $15, %r9d       /* byte position left over from less32bytes case */
1830         /*
1831          * Setup %r10 value allows us to detect crossing a page boundary.
1832          * When %r10 goes positive we have crossed a page boundary and
1833          * need to do a nibble.
1834          */
1835         lea     15(%rdi), %r10
1836         and     $0xfff, %r10    /* offset into 4K page */
1838         sub     $0x1000, %r10   /* subtract 4K pagesize */
1840         .p2align 4
1841 LABEL(loop_ashr_15):
1842         add     $16, %r10
1843         jg      LABEL(nibble_ashr_15)
1845 LABEL(gobble_ashr_15):
1846         movdqa  (%rsi, %rcx), %xmm1
1847         movdqa  (%rdi, %rcx), %xmm2
1848         movdqa  %xmm2, %xmm4
1850         psrldq  $15, %xmm3
1851         pslldq  $1, %xmm2
1852         por     %xmm3, %xmm2
1854         pcmpeqb %xmm1, %xmm0
1855         pcmpeqb %xmm2, %xmm1
1856         psubb   %xmm0, %xmm1
1857         pmovmskb %xmm1, %edx
1858         sub     $0xffff, %edx
1859         jnz     LABEL(exit)
1861 #ifdef USE_AS_STRNCMP
1862         sub     $16, %r11
1863         jbe     LABEL(strcmp_exitz)
1864 #endif
1866         add     $16, %rcx
1867         movdqa  %xmm4, %xmm3
1869         add     $16, %r10
1870         jg      LABEL(nibble_ashr_15)   /* cross page boundary */
1872         movdqa  (%rsi, %rcx), %xmm1
1873         movdqa  (%rdi, %rcx), %xmm2
1874         movdqa  %xmm2, %xmm4
1876         psrldq  $15, %xmm3
1877         pslldq  $1, %xmm2
1878         por     %xmm3, %xmm2
1880         pcmpeqb %xmm1, %xmm0
1881         pcmpeqb %xmm2, %xmm1
1882         psubb   %xmm0, %xmm1
1883         pmovmskb %xmm1, %edx
1884         sub     $0xffff, %edx
1885         jnz     LABEL(exit)
1887 #ifdef USE_AS_STRNCMP
1888         sub     $16, %r11
1889         jbe     LABEL(strcmp_exitz)
1890 #endif
1892         add     $16, %rcx
1893         movdqa  %xmm4, %xmm3
1894         jmp     LABEL(loop_ashr_15)
1896         .p2align 4
1897 LABEL(nibble_ashr_15):
1898         pcmpeqb %xmm3, %xmm0            /* check nibble for null char */
1899         pmovmskb %xmm0, %edx
1900         test    $0x8000, %edx
1901         jnz     LABEL(ashr_15_exittail)
1903 #ifdef USE_AS_STRNCMP
1904         test    %r11, %r11
1905         je      LABEL(ashr_15_exittail)
1906 #endif
1908         pxor    %xmm0, %xmm0
1909         sub     $0x1000, %r10
1910         jmp     LABEL(gobble_ashr_15)
1912         .p2align 4
1913 LABEL(ashr_15_exittail):
1914         movdqa  (%rsi, %rcx), %xmm1
1915         psrldq  $15, %xmm3
1916         psrldq  $15, %xmm0
1918         .p2align 4
1919 LABEL(aftertail):
1920         pcmpeqb %xmm3, %xmm1
1921         psubb   %xmm0, %xmm1
1922         pmovmskb %xmm1, %edx
1923         not     %edx
1925         .p2align 4
1926 LABEL(exit):
1927         lea     -16(%r9, %rcx), %rax    /* locate the exact offset for rdi */
1928 LABEL(less32bytes):
1929         lea     (%rdi, %rax), %rdi      /* locate the exact address for first operand(rdi) */
1930         lea     (%rsi, %rcx), %rsi      /* locate the exact address for second operand(rsi) */
1931         test    %r8d, %r8d
1932         jz      LABEL(ret)
1933         xchg    %rsi, %rdi              /* recover original order according to flag(%r8d) */
1935         .p2align 4
1936 LABEL(ret):
1937 LABEL(less16bytes):
1938         bsf     %rdx, %rdx              /* find and store bit index in %rdx */
1940 #ifdef USE_AS_STRNCMP
1941         sub     %rdx, %r11
1942         jbe     LABEL(strcmp_exitz)
1943 #endif
1944         movzbl  (%rsi, %rdx), %ecx
1945         movzbl  (%rdi, %rdx), %eax
1947         sub     %ecx, %eax
1948         ret
1950 LABEL(strcmp_exitz):
1951         xor     %eax, %eax
1952         ret
1954         .p2align 4
1955 LABEL(Byte0):
1956         movzx   (%rsi), %ecx
1957         movzx   (%rdi), %eax
1959         sub     %ecx, %eax
1960         ret
1961 END (BP_SYM (STRCMP))
1963         .section .rodata,"a",@progbits
1964         .p2align 3
1965 LABEL(unaligned_table):
1966         .int    LABEL(ashr_1) - LABEL(unaligned_table)
1967         .int    LABEL(ashr_2) - LABEL(unaligned_table)
1968         .int    LABEL(ashr_3) - LABEL(unaligned_table)
1969         .int    LABEL(ashr_4) - LABEL(unaligned_table)
1970         .int    LABEL(ashr_5) - LABEL(unaligned_table)
1971         .int    LABEL(ashr_6) - LABEL(unaligned_table)
1972         .int    LABEL(ashr_7) - LABEL(unaligned_table)
1973         .int    LABEL(ashr_8) - LABEL(unaligned_table)
1974         .int    LABEL(ashr_9) - LABEL(unaligned_table)
1975         .int    LABEL(ashr_10) - LABEL(unaligned_table)
1976         .int    LABEL(ashr_11) - LABEL(unaligned_table)
1977         .int    LABEL(ashr_12) - LABEL(unaligned_table)
1978         .int    LABEL(ashr_13) - LABEL(unaligned_table)
1979         .int    LABEL(ashr_14) - LABEL(unaligned_table)
1980         .int    LABEL(ashr_15) - LABEL(unaligned_table)
1981         .int    LABEL(ashr_0) - LABEL(unaligned_table)
1982 #endif /* NOT_IN_libc */
1983 libc_hidden_builtin_def (STRCMP)