Benchtests: Remove broken walk benchmarks
[glibc.git] / sysdeps / powerpc / powerpc32 / power7 / strnlen.S
blobe8e9db8d5afa8f26d782c177c0de85127a393a7c
1 /* Optimized strnlen implementation for PowerPC32/POWER7 using cmpb insn.
2    Copyright (C) 2010-2024 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, see
17    <https://www.gnu.org/licenses/>.  */
19 #include <sysdep.h>
21 /* int [r3] strnlen (char *s [r3], int size [r4])  */
22         .machine  power7
23 ENTRY (__strnlen)
24         CALL_MCOUNT
25         dcbt    0,r3
26         clrrwi  r8,r3,2       /* Align the address to word boundary.  */
27         add     r7,r3,r4      /* Calculate the last acceptable address.  */
28         cmplwi  r4,16
29         li      r0,0          /* Word with null chars.  */
30         addi    r7,r7,-1
31         ble     L(small_range)
33         rlwinm  r6,r3,3,27,28 /* Calculate padding.  */
34         lwz     r12,0(r8)     /* Load word from memory.  */
35         cmpb    r10,r12,r0    /* Check for null bytes in DWORD1.  */
36 #ifdef __LITTLE_ENDIAN__
37         srw     r10,r10,r6
38         slw     r10,r10,r6
39 #else
40         slw     r10,r10,r6
41         srw     r10,r10,r6
42 #endif
43         cmplwi  cr7,r10,0     /* If r10 == 0, no null's have been found.  */
44         bne     cr7,L(done)
46         clrrwi  r7,r7,2       /* Address of last word.  */
47         mtcrf   0x01,r8
48         /* Are we now aligned to a doubleword boundary?  If so, skip to
49            the main loop.  Otherwise, go through the alignment code.  */
51         bt      29,L(loop_setup)
53         /* Handle WORD2 of pair.  */
54         lwzu    r12,4(r8)
55         cmpb    r10,r12,r0
56         cmplwi  cr7,r10,0
57         bne     cr7,L(done)
59 L(loop_setup):
60         /* The last word we want to read in the loop below is the one
61            containing the last byte of the string, ie. the word at
62            (s + size - 1) & ~3, or r7.  The first word read is at
63            r8 + 4, we read 2 * cnt words, so the last word read will
64            be at r8 + 4 + 8 * cnt - 4.  Solving for cnt gives
65            cnt = (r7 - r8) / 8  */
66         sub     r5,r7,r8
67         srwi    r6,r5,3       /* Number of loop iterations.  */
68         mtctr   r6            /* Setup the counter.  */
70         /* Main loop to look for the null byte in the string.  Since
71            it's a small loop (< 8 instructions), align it to 32-bytes.  */
72         .p2align  5
73 L(loop):
74         /* Load two words, compare and merge in a
75            single register for speed.  This is an attempt
76            to speed up the null-checking process for bigger strings.  */
78         lwz     r12,4(r8)
79         lwzu    r11,8(r8)
80         cmpb    r10,r12,r0
81         cmpb    r9,r11,r0
82         or      r5,r9,r10     /* Merge everything in one word.  */
83         cmplwi  cr7,r5,0
84         bne     cr7,L(found)
85         bdnz    L(loop)
87         /* We may have one more word to read.  */
88         cmplw   cr6,r8,r7
89         beq     cr6,L(end_max)
91         lwzu    r12,4(r8)
92         cmpb    r10,r12,r0
93         cmplwi  cr6,r10,0
94         bne     cr6,L(done)
96 L(end_max):
97         mr      r3,r4
98         blr
100         /* OK, one (or both) of the words contains a null byte.  Check
101            the first word and decrement the address in case the first
102            word really contains a null byte.  */
103         .align  4
104 L(found):
105         cmplwi  cr6,r10,0
106         addi    r8,r8,-4
107         bne     cr6,L(done)
109         /* The null byte must be in the second word.  Adjust the address
110            again and move the result of cmpb to r10 so we can calculate the
111            length.  */
113         mr      r10,r9
114         addi    r8,r8,4
116         /* r10 has the output of the cmpb instruction, that is, it contains
117            0xff in the same position as the null byte in the original
118            word from the string.  Use that to calculate the length.
119            We need to make sure the null char is *before* the end of the
120            range.  */
121 L(done):
122 #ifdef __LITTLE_ENDIAN__
123         addi    r0,r10,-1
124         andc    r0,r0,r10
125         popcntw r0,r0
126 #else
127         cntlzw  r0,r10        /* Count leading zeros before the match.  */
128 #endif
129         sub     r3,r8,r3
130         srwi    r0,r0,3       /* Convert leading/trailing zeros to bytes.  */
131         add     r3,r3,r0      /* Length until the match.  */
132         cmplw   r3,r4
133         blelr
134         mr      r3,r4
135         blr
137 /* Deals with size <= 16.  */
138         .align  4
139 L(small_range):
140         cmplwi  r4,0
141         beq     L(end_max)
143         clrrwi  r7,r7,2       /* Address of last word.  */
145         rlwinm  r6,r3,3,27,28 /* Calculate padding.  */
146         lwz     r12,0(r8)     /* Load word from memory.  */
147         cmpb    r10,r12,r0    /* Check for null bytes in WORD1.  */
148 #ifdef __LITTLE_ENDIAN__
149         srw     r10,r10,r6
150         slw     r10,r10,r6
151 #else
152         slw     r10,r10,r6
153         srw     r10,r10,r6
154 #endif
155         cmplwi  cr7,r10,0
156         bne     cr7,L(done)
158         cmplw   r8,r7
159         beq     L(end_max)
161         .p2align  5
162 L(loop_small):
163         lwzu    r12,4(r8)
164         cmpb    r10,r12,r0
165         cmplwi  cr6,r10,0
166         bne     cr6,L(done)
167         cmplw   r8,r7
168         bne     L(loop_small)
169         mr      r3,r4
170         blr
172 END (__strnlen)
173 libc_hidden_def (__strnlen)
174 weak_alias (__strnlen, strnlen)
175 libc_hidden_builtin_def (strnlen)