2 * strchr - find a character in a string
4 * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5 * See https://llvm.org/LICENSE.txt for license information.
6 * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
15 #include "../asmdefs.h"
17 /* Arguments and results. */
41 For each 16-byte chunk we calculate a 64-bit syndrome value, with
42 four bits per byte (LSB is always in bits 0 and 1, for both big
43 and little-endian systems). For each tuple, bit 0 is set if
44 the relevant byte matched the requested character; bit 1 is set
45 if the relevant byte matched the NUL end of string (we trigger
46 off bit0 for the special case of looking for NUL) and bits 2 and 3
48 Since the bits in the syndrome reflect exactly the order in which
49 things occur in the original string a count_trailing_zeros()
50 operation will identify exactly which byte is causing the termination,
53 /* Locals and temporaries. */
55 ENTRY(__strchr_aarch64_mte)
56 /* Magic constant 0x10011001 to allow us to identify which lane
57 matches the requested byte. Magic constant 0x20022002 used
58 similarly for NUL termination. */
60 movk wtmp2, #0x1001, lsl #16
61 dup vrepchr.16b, chrin
62 bic src, srcin, #15 /* Work with aligned 16-byte chunks. */
63 dup vrepmask_c.4s, wtmp2
65 add vrepmask_0.4s, vrepmask_c.4s, vrepmask_c.4s /* equiv: lsl #1 */
68 /* Input string is not 16-byte aligned. Rather than forcing
69 the padding bytes to a safe value, we calculate the syndrome
70 for all the bytes, but then mask off those bits of the
71 syndrome that are related to the padding. */
73 cmeq vhas_nul.16b, vdata.16b, #0
74 cmeq vhas_chr.16b, vdata.16b, vrepchr.16b
75 and vhas_nul.16b, vhas_nul.16b, vrepmask_0.16b
76 and vhas_chr.16b, vhas_chr.16b, vrepmask_c.16b
78 orr vend.16b, vhas_nul.16b, vhas_chr.16b
80 addp vend.16b, vend.16b, vend.16b /* 128->64 */
84 ands tmp1, tmp3, tmp1 /* Mask padding bits. */
89 cmeq vhas_nul.16b, vdata.16b, #0
90 cmeq vhas_chr.16b, vdata.16b, vrepchr.16b
91 /* Use a fast check for the termination condition. */
92 orr vend.16b, vhas_nul.16b, vhas_chr.16b
93 addp vend.16b, vend.16b, vend.16b /* 128->64 */
97 ldr qdata, [src, #-16]
98 cmeq vhas_nul.16b, vdata.16b, #0
99 cmeq vhas_chr.16b, vdata.16b, vrepchr.16b
100 /* Use a fast check for the termination condition. */
101 orr vend.16b, vhas_nul.16b, vhas_chr.16b
102 addp vend.16b, vend.16b, vend.16b /* 128->64 */
106 /* Adjust src for next two subtractions. */
109 /* Termination condition found. Now need to establish exactly why
111 and vhas_nul.16b, vhas_nul.16b, vrepmask_0.16b
112 and vhas_chr.16b, vhas_chr.16b, vrepmask_c.16b
114 orr vend.16b, vhas_nul.16b, vhas_chr.16b
115 addp vend.16b, vend.16b, vend.16b /* 128->64 */
119 /* Count the trailing zeros, by bit reversing... */
121 /* Re-bias source. */
123 clz tmp1, tmp1 /* And counting the leading zeros. */
124 /* Tmp1 is even if the target character was found first. Otherwise
125 we've found the end of string and we weren't looking for NUL. */
127 add result, src, tmp1, lsr #2
128 csel result, result, xzr, eq
131 END(__strchr_aarch64_mte)