Cygwin: access: Fix X_OK behaviour for backup operators and admins
[newlib-cygwin.git] / newlib / libc / machine / aarch64 / strnlen.S
blob091002e0b0b2f881f44985fd85afd56dbca8f0c1
1 /*
2  * strnlen - calculate the length of a string with limit.
3  *
4  * Copyright (c) 2020-2022, Arm Limited.
5  * SPDX-License-Identifier: MIT OR Apache-2.0 WITH LLVM-exception
6  */
7 #if (defined (__OPTIMIZE_SIZE__) || defined (PREFER_SIZE_OVER_SPEED))
8 /* See strlen-stub.c  */
9 #else
11 /* Assumptions:
12  *
13  * ARMv8-a, AArch64, Advanced SIMD.
14  * MTE compatible.
15  */
17 #include "asmdefs.h"
19 #define srcin           x0
20 #define cntin           x1
21 #define result          x0
23 #define src             x2
24 #define synd            x3
25 #define shift           x4
26 #define tmp             x4
27 #define cntrem          x5
29 #define qdata           q0
30 #define vdata           v0
31 #define vhas_chr        v1
32 #define vend            v2
33 #define dend            d2
36    Core algorithm:
37    Process the string in 16-byte aligned chunks. Compute a 64-bit mask with
38    four bits per byte using the shrn instruction. A count trailing zeros then
39    identifies the first zero byte.  */
41 ENTRY (strnlen)
42         PTR_ARG (0)
43         SIZE_ARG (1)
44         bic     src, srcin, 15
45         cbz     cntin, L(nomatch)
46         ld1     {vdata.16b}, [src]
47         cmeq    vhas_chr.16b, vdata.16b, 0
48         lsl     shift, srcin, 2
49         shrn    vend.8b, vhas_chr.8h, 4         /* 128->64 */
50         fmov    synd, dend
51         lsr     synd, synd, shift
52         cbz     synd, L(start_loop)
53 L(finish):
54         rbit    synd, synd
55         clz     synd, synd
56         lsr     result, synd, 2
57         cmp     cntin, result
58         csel    result, cntin, result, ls
59         ret
61 L(nomatch):
62         mov     result, cntin
63         ret
65 L(start_loop):
66         sub     tmp, src, srcin
67         add     tmp, tmp, 17
68         subs    cntrem, cntin, tmp
69         b.lo    L(nomatch)
71         /* Make sure that it won't overread by a 16-byte chunk */
72         tbz     cntrem, 4, L(loop32_2)
73         sub     src, src, 16
74         .p2align 5
75 L(loop32):
76         ldr     qdata, [src, 32]!
77         cmeq    vhas_chr.16b, vdata.16b, 0
78         umaxp   vend.16b, vhas_chr.16b, vhas_chr.16b            /* 128->64 */
79         fmov    synd, dend
80         cbnz    synd, L(end)
81 L(loop32_2):
82         ldr     qdata, [src, 16]
83         subs    cntrem, cntrem, 32
84         cmeq    vhas_chr.16b, vdata.16b, 0
85         b.lo    L(end_2)
86         umaxp   vend.16b, vhas_chr.16b, vhas_chr.16b            /* 128->64 */
87         fmov    synd, dend
88         cbz     synd, L(loop32)
89 L(end_2):
90         add     src, src, 16
91 L(end):
92         shrn    vend.8b, vhas_chr.8h, 4         /* 128->64 */
93         sub     result, src, srcin
94         fmov    synd, dend
95 #ifndef __AARCH64EB__
96         rbit    synd, synd
97 #endif
98         clz     synd, synd
99         add     result, result, synd, lsr 2
100         cmp     cntin, result
101         csel    result, cntin, result, ls
102         ret
104 END (strnlen)
105 #endif