1bbbf1280Sopenharmony_ci/* 2bbbf1280Sopenharmony_ci * strnlen - calculate the length of a string with limit. 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 (__strnlen_aarch64_sve) 18bbbf1280Sopenharmony_ci PTR_ARG (0) 19bbbf1280Sopenharmony_ci SIZE_ARG (1) 20bbbf1280Sopenharmony_ci setffr /* initialize FFR */ 21bbbf1280Sopenharmony_ci mov x2, 0 /* initialize len */ 22bbbf1280Sopenharmony_ci b 1f 23bbbf1280Sopenharmony_ci 24bbbf1280Sopenharmony_ci .p2align 4 25bbbf1280Sopenharmony_ci /* We have off + vl <= max, and so may read the whole vector. */ 26bbbf1280Sopenharmony_ci0: ldff1b z0.b, p0/z, [x0, x2] 27bbbf1280Sopenharmony_ci rdffrs p1.b, p0/z 28bbbf1280Sopenharmony_ci b.nlast 2f 29bbbf1280Sopenharmony_ci 30bbbf1280Sopenharmony_ci /* First fault did not fail: the whole vector is valid. 31bbbf1280Sopenharmony_ci Avoid depending on the contents of FFR beyond the branch. */ 32bbbf1280Sopenharmony_ci cmpeq p2.b, p0/z, z0.b, 0 33bbbf1280Sopenharmony_ci b.any 8f 34bbbf1280Sopenharmony_ci incb x2 35bbbf1280Sopenharmony_ci 36bbbf1280Sopenharmony_ci1: whilelo p0.b, x2, x1 37bbbf1280Sopenharmony_ci b.last 0b 38bbbf1280Sopenharmony_ci 39bbbf1280Sopenharmony_ci /* We have off + vl < max. Test for off == max before proceeding. */ 40bbbf1280Sopenharmony_ci b.none 9f 41bbbf1280Sopenharmony_ci 42bbbf1280Sopenharmony_ci ldff1b z0.b, p0/z, [x0, x2] 43bbbf1280Sopenharmony_ci rdffrs p1.b, p0/z 44bbbf1280Sopenharmony_ci b.nlast 2f 45bbbf1280Sopenharmony_ci 46bbbf1280Sopenharmony_ci /* First fault did not fail: the vector up to max is valid. 47bbbf1280Sopenharmony_ci Avoid depending on the contents of FFR beyond the branch. 48bbbf1280Sopenharmony_ci Compare for end-of-string, but there are no more bytes. */ 49bbbf1280Sopenharmony_ci cmpeq p2.b, p0/z, z0.b, 0 50bbbf1280Sopenharmony_ci 51bbbf1280Sopenharmony_ci /* Found end-of-string or zero. */ 52bbbf1280Sopenharmony_ci8: brkb p2.b, p0/z, p2.b 53bbbf1280Sopenharmony_ci mov x0, x2 54bbbf1280Sopenharmony_ci incp x0, p2.b 55bbbf1280Sopenharmony_ci ret 56bbbf1280Sopenharmony_ci 57bbbf1280Sopenharmony_ci /* First fault failed: only some of the vector is valid. 58bbbf1280Sopenharmony_ci Perform the comparison only on the valid bytes. */ 59bbbf1280Sopenharmony_ci2: cmpeq p2.b, p1/z, z0.b, 0 60bbbf1280Sopenharmony_ci b.any 8b 61bbbf1280Sopenharmony_ci 62bbbf1280Sopenharmony_ci /* No inequality or zero found. Re-init FFR, incr and loop. */ 63bbbf1280Sopenharmony_ci setffr 64bbbf1280Sopenharmony_ci incp x2, p1.b 65bbbf1280Sopenharmony_ci b 1b 66bbbf1280Sopenharmony_ci 67bbbf1280Sopenharmony_ci /* End of count. Return max. */ 68bbbf1280Sopenharmony_ci9: mov x0, x1 69bbbf1280Sopenharmony_ci ret 70bbbf1280Sopenharmony_ci 71bbbf1280Sopenharmony_ciEND (__strnlen_aarch64_sve) 72bbbf1280Sopenharmony_ci 73bbbf1280Sopenharmony_ci#endif 74bbbf1280Sopenharmony_ci 75