1/* 2 * strrchr - find the last of a character in a string 3 * 4 * Copyright (c) 2019-2021, Arm Limited. 5 * SPDX-License-Identifier: MIT 6 */ 7 8#include "../asmdefs.h" 9 10#if __ARM_FEATURE_SVE 11/* Assumptions: 12 * 13 * ARMv8-a, AArch64 14 * SVE Available. 15 */ 16 17ENTRY (__strrchr_aarch64_sve) 18 PTR_ARG (0) 19 dup z1.b, w1 /* replicate byte across vector */ 20 setffr /* initialize FFR */ 21 ptrue p1.b /* all ones; loop invariant */ 22 mov x2, 0 /* no match found so far */ 23 pfalse p2.b 24 25 .p2align 4 26 /* Read a vector's worth of bytes, stopping on first fault. */ 270: ldff1b z0.b, p1/z, [x0, xzr] 28 rdffrs p0.b, p1/z 29 b.nlast 1f 30 31 /* First fault did not fail: the whole vector is valid. 32 Avoid depending on the contents of FFR beyond the branch. */ 33 incb x0, all /* skip bytes this round */ 34 cmpeq p3.b, p1/z, z0.b, 0 /* search for 0 */ 35 b.any 3f 36 37 cmpeq p3.b, p1/z, z0.b, z1.b /* search for c; no eos */ 38 b.none 0b 39 40 mov x2, x0 /* save advanced base */ 41 mov p2.b, p3.b /* save current search */ 42 b 0b 43 44 /* First fault failed: only some of the vector is valid. 45 Perform the comparisions only on the valid bytes. */ 461: cmpeq p3.b, p0/z, z0.b, 0 /* search for 0 */ 47 b.any 2f 48 49 cmpeq p3.b, p0/z, z0.b, z1.b /* search for c; no eos */ 50 mov x3, x0 51 incp x0, p0.b /* skip bytes this round */ 52 setffr /* re-init FFR */ 53 b.none 0b 54 55 addvl x2, x3, 1 /* save advanced base */ 56 mov p2.b, p3.b /* save current search */ 57 b 0b 58 59 /* Found end-of-string. */ 602: incb x0, all /* advance base */ 613: brka p3.b, p1/z, p3.b /* mask after first 0 */ 62 cmpeq p3.b, p3/z, z0.b, z1.b /* search for c not after eos */ 63 b.any 4f 64 65 /* No C within last vector. Did we have one before? */ 66 cbz x2, 5f 67 mov x0, x2 /* restore advanced base */ 68 mov p3.b, p2.b /* restore saved search */ 69 70 /* Find the *last* match in the predicate. This is slightly 71 more complicated than finding the first match. */ 724: rev p3.b, p3.b /* reverse the bits */ 73 brka p3.b, p1/z, p3.b /* find position of last match */ 74 decp x0, p3.b /* retard pointer to last match */ 75 ret 76 77 /* No C whatsoever. Return NULL. */ 785: mov x0, 0 79 ret 80 81END (__strrchr_aarch64_sve) 82 83#endif 84 85