1bbbf1280Sopenharmony_ci/* 2bbbf1280Sopenharmony_ci * strrchr - find the last of a character in a string 3bbbf1280Sopenharmony_ci * 4bbbf1280Sopenharmony_ci * Copyright (c) 2019-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_ciENTRY (__strrchr_aarch64_sve) 18bbbf1280Sopenharmony_ci PTR_ARG (0) 19bbbf1280Sopenharmony_ci dup z1.b, w1 /* replicate byte across vector */ 20bbbf1280Sopenharmony_ci setffr /* initialize FFR */ 21bbbf1280Sopenharmony_ci ptrue p1.b /* all ones; loop invariant */ 22bbbf1280Sopenharmony_ci mov x2, 0 /* no match found so far */ 23bbbf1280Sopenharmony_ci pfalse p2.b 24bbbf1280Sopenharmony_ci 25bbbf1280Sopenharmony_ci .p2align 4 26bbbf1280Sopenharmony_ci /* Read a vector's worth of bytes, stopping on first fault. */ 27bbbf1280Sopenharmony_ci0: ldff1b z0.b, p1/z, [x0, xzr] 28bbbf1280Sopenharmony_ci rdffrs p0.b, p1/z 29bbbf1280Sopenharmony_ci b.nlast 1f 30bbbf1280Sopenharmony_ci 31bbbf1280Sopenharmony_ci /* First fault did not fail: the whole vector is valid. 32bbbf1280Sopenharmony_ci Avoid depending on the contents of FFR beyond the branch. */ 33bbbf1280Sopenharmony_ci incb x0, all /* skip bytes this round */ 34bbbf1280Sopenharmony_ci cmpeq p3.b, p1/z, z0.b, 0 /* search for 0 */ 35bbbf1280Sopenharmony_ci b.any 3f 36bbbf1280Sopenharmony_ci 37bbbf1280Sopenharmony_ci cmpeq p3.b, p1/z, z0.b, z1.b /* search for c; no eos */ 38bbbf1280Sopenharmony_ci b.none 0b 39bbbf1280Sopenharmony_ci 40bbbf1280Sopenharmony_ci mov x2, x0 /* save advanced base */ 41bbbf1280Sopenharmony_ci mov p2.b, p3.b /* save current search */ 42bbbf1280Sopenharmony_ci b 0b 43bbbf1280Sopenharmony_ci 44bbbf1280Sopenharmony_ci /* First fault failed: only some of the vector is valid. 45bbbf1280Sopenharmony_ci Perform the comparisions only on the valid bytes. */ 46bbbf1280Sopenharmony_ci1: cmpeq p3.b, p0/z, z0.b, 0 /* search for 0 */ 47bbbf1280Sopenharmony_ci b.any 2f 48bbbf1280Sopenharmony_ci 49bbbf1280Sopenharmony_ci cmpeq p3.b, p0/z, z0.b, z1.b /* search for c; no eos */ 50bbbf1280Sopenharmony_ci mov x3, x0 51bbbf1280Sopenharmony_ci incp x0, p0.b /* skip bytes this round */ 52bbbf1280Sopenharmony_ci setffr /* re-init FFR */ 53bbbf1280Sopenharmony_ci b.none 0b 54bbbf1280Sopenharmony_ci 55bbbf1280Sopenharmony_ci addvl x2, x3, 1 /* save advanced base */ 56bbbf1280Sopenharmony_ci mov p2.b, p3.b /* save current search */ 57bbbf1280Sopenharmony_ci b 0b 58bbbf1280Sopenharmony_ci 59bbbf1280Sopenharmony_ci /* Found end-of-string. */ 60bbbf1280Sopenharmony_ci2: incb x0, all /* advance base */ 61bbbf1280Sopenharmony_ci3: brka p3.b, p1/z, p3.b /* mask after first 0 */ 62bbbf1280Sopenharmony_ci cmpeq p3.b, p3/z, z0.b, z1.b /* search for c not after eos */ 63bbbf1280Sopenharmony_ci b.any 4f 64bbbf1280Sopenharmony_ci 65bbbf1280Sopenharmony_ci /* No C within last vector. Did we have one before? */ 66bbbf1280Sopenharmony_ci cbz x2, 5f 67bbbf1280Sopenharmony_ci mov x0, x2 /* restore advanced base */ 68bbbf1280Sopenharmony_ci mov p3.b, p2.b /* restore saved search */ 69bbbf1280Sopenharmony_ci 70bbbf1280Sopenharmony_ci /* Find the *last* match in the predicate. This is slightly 71bbbf1280Sopenharmony_ci more complicated than finding the first match. */ 72bbbf1280Sopenharmony_ci4: rev p3.b, p3.b /* reverse the bits */ 73bbbf1280Sopenharmony_ci brka p3.b, p1/z, p3.b /* find position of last match */ 74bbbf1280Sopenharmony_ci decp x0, p3.b /* retard pointer to last match */ 75bbbf1280Sopenharmony_ci ret 76bbbf1280Sopenharmony_ci 77bbbf1280Sopenharmony_ci /* No C whatsoever. Return NULL. */ 78bbbf1280Sopenharmony_ci5: mov x0, 0 79bbbf1280Sopenharmony_ci ret 80bbbf1280Sopenharmony_ci 81bbbf1280Sopenharmony_ciEND (__strrchr_aarch64_sve) 82bbbf1280Sopenharmony_ci 83bbbf1280Sopenharmony_ci#endif 84bbbf1280Sopenharmony_ci 85