1 /* strchr - find a character in a string
3 Copyright (C) 2014-2017 Free Software Foundation, Inc.
5 This file is part of the GNU C Library.
7 The GNU C Library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Lesser General Public
9 License as published by the Free Software Foundation; either
10 version 2.1 of the License, or (at your option) any later version.
12 The GNU C Library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public
18 License along with the GNU C Library. If not, see
19 <http://www.gnu.org/licenses/>. */
28 /* Arguments and results. */
47 #define vrepmask_c v16
52 For each 32-byte hunk we calculate a 64-bit syndrome value, with
53 two bits per byte (LSB is always in bits 0 and 1, for both big
54 and little-endian systems). Bit 0 is set iff the relevant byte
55 matched the requested character. Bit 1 is set iff the
56 relevant byte matched the NUL end of string (we trigger off bit0
57 for the special case of looking for NUL). Since the bits
58 in the syndrome reflect exactly the order in which things occur
59 in the original string a count_trailing_zeros() operation will
60 identify exactly which byte is causing the termination, and why. */
62 /* Locals and temporaries. */
67 movk wtmp2, #0x4010, lsl #16
68 dup vrepchr.16b, chrin
70 dup vrepmask_c.4s, wtmp2
72 add vrepmask_0.4s, vrepmask_c.4s, vrepmask_c.4s // lsl #1
75 /* Input string is not 32-byte aligned. Rather than forcing
76 the padding bytes to a safe value, we calculate the syndrome
77 for all the bytes, but then mask off those bits of the
78 syndrome that are related to the padding. */
79 ld1 {vdata1.16b, vdata2.16b}, [src], #32
81 cmeq vhas_nul1.16b, vdata1.16b, #0
82 cmeq vhas_chr1.16b, vdata1.16b, vrepchr.16b
83 cmeq vhas_nul2.16b, vdata2.16b, #0
84 cmeq vhas_chr2.16b, vdata2.16b, vrepchr.16b
85 and vhas_nul1.16b, vhas_nul1.16b, vrepmask_0.16b
86 and vhas_nul2.16b, vhas_nul2.16b, vrepmask_0.16b
87 and vhas_chr1.16b, vhas_chr1.16b, vrepmask_c.16b
88 and vhas_chr2.16b, vhas_chr2.16b, vrepmask_c.16b
89 orr vend1.16b, vhas_nul1.16b, vhas_chr1.16b
90 orr vend2.16b, vhas_nul2.16b, vhas_chr2.16b
92 addp vend1.16b, vend1.16b, vend2.16b // 256->128
94 addp vend1.16b, vend1.16b, vend2.16b // 128->64
98 bic tmp1, tmp3, tmp1 // Mask padding bits.
102 ld1 {vdata1.16b, vdata2.16b}, [src], #32
103 cmeq vhas_nul1.16b, vdata1.16b, #0
104 cmeq vhas_chr1.16b, vdata1.16b, vrepchr.16b
105 cmeq vhas_nul2.16b, vdata2.16b, #0
106 cmeq vhas_chr2.16b, vdata2.16b, vrepchr.16b
107 /* Use a fast check for the termination condition. */
108 orr vend1.16b, vhas_nul1.16b, vhas_chr1.16b
109 orr vend2.16b, vhas_nul2.16b, vhas_chr2.16b
110 orr vend1.16b, vend1.16b, vend2.16b
111 addp vend1.2d, vend1.2d, vend1.2d
112 mov tmp1, vend1.2d[0]
115 /* Termination condition found. Now need to establish exactly why
117 and vhas_nul1.16b, vhas_nul1.16b, vrepmask_0.16b
118 and vhas_nul2.16b, vhas_nul2.16b, vrepmask_0.16b
119 and vhas_chr1.16b, vhas_chr1.16b, vrepmask_c.16b
120 and vhas_chr2.16b, vhas_chr2.16b, vrepmask_c.16b
121 orr vend1.16b, vhas_nul1.16b, vhas_chr1.16b
122 orr vend2.16b, vhas_nul2.16b, vhas_chr2.16b
123 addp vend1.16b, vend1.16b, vend2.16b // 256->128
124 addp vend1.16b, vend1.16b, vend2.16b // 128->64
126 mov tmp1, vend1.2d[0]
131 /* Tmp1 is even if the target charager was found first. Otherwise
132 we've found the end of string and we weren't looking for NUL. */
134 add result, src, tmp1, lsr #1
135 csel result, result, xzr, eq
138 libc_hidden_builtin_def (strchr)
139 weak_alias (strchr, index)