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