1 /* Optimized strchrnul implementation for PowerPC64/POWER7 using cmpb insn.
2 Copyright (C) 2010-2014 Free Software Foundation, Inc.
3 Contributed by Luis Machado <luisgpm@br.ibm.com>.
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, see
18 <http://www.gnu.org/licenses/>. */
22 /* int [r3] strchrnul (char *s [r3], int c [r4]) */
27 clrrdi r8,r3,3 /* Align the address to doubleword boundary. */
29 /* Replicate byte to doubleword. */
34 rlwinm r6,r3,3,26,28 /* Calculate padding. */
35 ld r12,0(r8) /* Load doubleword from memory. */
36 li r0,0 /* Doubleword with null chars to use
39 /* Now r4 has a doubleword of c bytes and r0 has
40 a doubleword of null bytes. */
42 cmpb r10,r12,r0 /* Compare each byte against c byte. */
43 cmpb r9,r12,r4 /* Compare each byte against null byte. */
45 /* Move the doublewords left and right to discard the bits that are
46 not part of the string and to bring them back as zeros. */
47 #ifdef __LITTLE_ENDIAN__
58 or r5,r9,r10 /* OR the results to speed things up. */
59 cmpdi cr7,r5,0 /* If r5 == 0, no c or null bytes
65 /* Are we now aligned to a quadword boundary? If so, skip to
66 the main loop. Otherwise, go through the alignment code. */
70 /* Handle DWORD2 of pair. */
77 b L(loop) /* We branch here (rather than falling through)
78 to skip the nops due to heavy alignment
83 /* Load two doublewords, compare and merge in a
84 single register for speed. This is an attempt
85 to speed up the null-checking process for bigger strings. */
98 /* OK, one (or both) of the doublewords contains a c/null byte. Check
99 the first doubleword and decrement the address in case the first
100 doubleword really contains a c/null byte. */
106 /* The c/null byte must be in the second doubleword. Adjust the
107 address again and move the result of cmpb to r5 so we can calculate
112 /* r5 has the output of the cmpb instruction, that is, it contains
113 0xff in the same position as the c/null byte in the original
114 doubleword from the string. Use that to calculate the pointer. */
116 #ifdef __LITTLE_ENDIAN__
121 cntlzd r0,r5 /* Count leading zeros before the match. */
123 srdi r0,r0,3 /* Convert leading zeros to bytes. */
124 add r3,r8,r0 /* Return address of matching c/null byte. */
127 weak_alias (__strchrnul,strchrnul)
128 libc_hidden_builtin_def (__strchrnul)