1 | /* |
2 | * strchr/strchrnul - find a character in a string |
3 | * |
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 |
7 | */ |
8 | |
9 | #if __ARM_FEATURE_SVE |
10 | /* Assumptions: |
11 | * |
12 | * ARMv8-a, AArch64 |
13 | * SVE Available. |
14 | */ |
15 | |
16 | .arch armv8-a+sve |
17 | .text |
18 | |
19 | /* To build as strchrnul, define BUILD_STRCHRNUL before compiling this file. */ |
20 | #ifdef BUILD_STRCHRNUL |
21 | #define FUNC __strchrnul_aarch64_sve |
22 | #else |
23 | #define FUNC __strchr_aarch64_sve |
24 | #endif |
25 | |
26 | .globl FUNC |
27 | .type FUNC, %function |
28 | .p2align 4 |
29 | FUNC: |
30 | dup z1.b, w1 /* replicate byte across vector */ |
31 | setffr /* initialize FFR */ |
32 | ptrue p1.b /* all ones; loop invariant */ |
33 | |
34 | .p2align 4 |
35 | /* Read a vector's worth of bytes, stopping on first fault. */ |
36 | 0: ldff1b z0.b, p1/z, [x0, xzr] |
37 | rdffrs p0.b, p1/z |
38 | b.nlast 2f |
39 | |
40 | /* First fault did not fail: the whole vector is valid. |
41 | Avoid depending on the contents of FFR beyond the branch. */ |
42 | incb x0 /* speculate increment */ |
43 | cmpeq p2.b, p1/z, z0.b, z1.b /* search for c */ |
44 | cmpeq p3.b, p1/z, z0.b, 0 /* search for 0 */ |
45 | orrs p4.b, p1/z, p2.b, p3.b /* c | 0 */ |
46 | b.none 0b |
47 | decb x0 /* undo speculate */ |
48 | |
49 | /* Found C or 0. */ |
50 | 1: brka p4.b, p1/z, p4.b /* find first such */ |
51 | sub x0, x0, 1 /* adjust pointer for that byte */ |
52 | incp x0, p4.b |
53 | #ifndef BUILD_STRCHRNUL |
54 | ptest p4, p2.b /* was first in c? */ |
55 | csel x0, xzr, x0, none /* if there was no c, return null */ |
56 | #endif |
57 | ret |
58 | |
59 | /* First fault failed: only some of the vector is valid. |
60 | Perform the comparison only on the valid bytes. */ |
61 | 2: cmpeq p2.b, p0/z, z0.b, z1.b /* search for c */ |
62 | cmpeq p3.b, p0/z, z0.b, 0 /* search for 0 */ |
63 | orrs p4.b, p0/z, p2.b, p3.b /* c | 0 */ |
64 | b.any 1b |
65 | |
66 | /* No C or 0 found. Re-init FFR, increment, and loop. */ |
67 | setffr |
68 | incp x0, p0.b |
69 | b 0b |
70 | |
71 | .size FUNC, . - FUNC |
72 | #endif |
73 | |