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