/* * strchr/strchrnul - find a character in a string * * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. * See https://llvm.org/LICENSE.txt for license information. * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception */ #if __ARM_FEATURE_SVE /* Assumptions: * * ARMv8-a, AArch64 * SVE Available. */ .arch armv8-a+sve .text /* To build as strchrnul, define BUILD_STRCHRNUL before compiling this file. */ #ifdef BUILD_STRCHRNUL #define FUNC __strchrnul_aarch64_sve #else #define FUNC __strchr_aarch64_sve #endif .globl FUNC .type FUNC, %function .p2align 4 FUNC: dup z1.b, w1 /* replicate byte across vector */ setffr /* initialize FFR */ ptrue p1.b /* all ones; loop invariant */ .p2align 4 /* Read a vector's worth of bytes, stopping on first fault. */ 0: ldff1b z0.b, p1/z, [x0, xzr] rdffrs p0.b, p1/z b.nlast 2f /* First fault did not fail: the whole vector is valid. Avoid depending on the contents of FFR beyond the branch. */ incb x0 /* speculate increment */ cmpeq p2.b, p1/z, z0.b, z1.b /* search for c */ cmpeq p3.b, p1/z, z0.b, 0 /* search for 0 */ orrs p4.b, p1/z, p2.b, p3.b /* c | 0 */ b.none 0b decb x0 /* undo speculate */ /* Found C or 0. */ 1: brka p4.b, p1/z, p4.b /* find first such */ sub x0, x0, 1 /* adjust pointer for that byte */ incp x0, p4.b #ifndef BUILD_STRCHRNUL ptest p4, p2.b /* was first in c? */ csel x0, xzr, x0, none /* if there was no c, return null */ #endif ret /* First fault failed: only some of the vector is valid. Perform the comparison only on the valid bytes. */ 2: cmpeq p2.b, p0/z, z0.b, z1.b /* search for c */ cmpeq p3.b, p0/z, z0.b, 0 /* search for 0 */ orrs p4.b, p0/z, p2.b, p3.b /* c | 0 */ b.any 1b /* No C or 0 found. Re-init FFR, increment, and loop. */ setffr incp x0, p0.b b 0b .size FUNC, . - FUNC #endif