Cygwin: access: Fix X_OK behaviour for backup operators and admins
[newlib-cygwin.git] / newlib / libc / machine / aarch64 / strcpy.S
blob57c46f390896b6663c2bd3e76c675b3f8668e7ee
1 /*
2  * strcpy/stpcpy - copy a string returning pointer to start/end.
3  *
4  * Copyright (c) 2020-2023, 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 strchr-stub.c  */
9 #else
11 /* Assumptions:
12  *
13  * ARMv8-a, AArch64, Advanced SIMD.
14  * MTE compatible.
15  */
17 #include "asmdefs.h"
19 #define dstin           x0
20 #define srcin           x1
21 #define result          x0
23 #define src             x2
24 #define dst             x3
25 #define len             x4
26 #define synd            x4
27 #define tmp             x5
28 #define shift           x5
29 #define data1           x6
30 #define dataw1          w6
31 #define data2           x7
32 #define dataw2          w7
34 #define dataq           q0
35 #define vdata           v0
36 #define vhas_nul        v1
37 #define vend            v2
38 #define dend            d2
39 #define dataq2          q1
41 #ifdef BUILD_STPCPY
42 # define STRCPY stpcpy
43 # define IFSTPCPY(X,...) X,__VA_ARGS__
44 #else
45 # define STRCPY strcpy
46 # define IFSTPCPY(X,...)
47 #endif
50    Core algorithm:
51    For each 16-byte chunk we calculate a 64-bit nibble mask value with four bits
52    per byte. We take 4 bits of every comparison byte with shift right and narrow
53    by 4 instruction. Since the bits in the nibble mask reflect the order in
54    which things occur in the original string, counting leading zeros identifies
55    exactly which byte matched.  */
57 ENTRY (STRCPY)
58         PTR_ARG (0)
59         PTR_ARG (1)
60         bic     src, srcin, 15
61         ld1     {vdata.16b}, [src]
62         cmeq    vhas_nul.16b, vdata.16b, 0
63         lsl     shift, srcin, 2
64         shrn    vend.8b, vhas_nul.8h, 4
65         fmov    synd, dend
66         lsr     synd, synd, shift
67         cbnz    synd, L(tail)
69         ldr     dataq, [src, 16]!
70         cmeq    vhas_nul.16b, vdata.16b, 0
71         shrn    vend.8b, vhas_nul.8h, 4
72         fmov    synd, dend
73         cbz     synd, L(start_loop)
75 #ifndef __AARCH64EB__
76         rbit    synd, synd
77 #endif
78         sub     tmp, src, srcin
79         clz     len, synd
80         add     len, tmp, len, lsr 2
81         tbz     len, 4, L(less16)
82         sub     tmp, len, 15
83         ldr     dataq, [srcin]
84         ldr     dataq2, [srcin, tmp]
85         str     dataq, [dstin]
86         str     dataq2, [dstin, tmp]
87         IFSTPCPY (add result, dstin, len)
88         ret
90 L(tail):
91         rbit    synd, synd
92         clz     len, synd
93         lsr     len, len, 2
94 L(less16):
95         tbz     len, 3, L(less8)
96         sub     tmp, len, 7
97         ldr     data1, [srcin]
98         ldr     data2, [srcin, tmp]
99         str     data1, [dstin]
100         str     data2, [dstin, tmp]
101         IFSTPCPY (add result, dstin, len)
102         ret
104         .p2align 4
105 L(less8):
106         subs    tmp, len, 3
107         b.lo    L(less4)
108         ldr     dataw1, [srcin]
109         ldr     dataw2, [srcin, tmp]
110         str     dataw1, [dstin]
111         str     dataw2, [dstin, tmp]
112         IFSTPCPY (add result, dstin, len)
113         ret
115 L(less4):
116         cbz     len, L(zerobyte)
117         ldrh    dataw1, [srcin]
118         strh    dataw1, [dstin]
119 L(zerobyte):
120         strb    wzr, [dstin, len]
121         IFSTPCPY (add result, dstin, len)
122         ret
124         .p2align 4
125 L(start_loop):
126         sub     tmp, srcin, dstin
127         ldr     dataq2, [srcin]
128         sub     dst, src, tmp
129         str     dataq2, [dstin]
130 L(loop):
131         str     dataq, [dst], 32
132         ldr     dataq, [src, 16]
133         cmeq    vhas_nul.16b, vdata.16b, 0
134         umaxp   vend.16b, vhas_nul.16b, vhas_nul.16b
135         fmov    synd, dend
136         cbnz    synd, L(loopend)
137         str     dataq, [dst, -16]
138         ldr     dataq, [src, 32]!
139         cmeq    vhas_nul.16b, vdata.16b, 0
140         umaxp   vend.16b, vhas_nul.16b, vhas_nul.16b
141         fmov    synd, dend
142         cbz     synd, L(loop)
143         add     dst, dst, 16
144 L(loopend):
145         shrn    vend.8b, vhas_nul.8h, 4         /* 128->64 */
146         fmov    synd, dend
147         sub     dst, dst, 31
148 #ifndef __AARCH64EB__
149         rbit    synd, synd
150 #endif
151         clz     len, synd
152         lsr     len, len, 2
153         add     dst, dst, len
154         ldr     dataq, [dst, tmp]
155         str     dataq, [dst]
156         IFSTPCPY (add result, dst, 15)
157         ret
159 END (STRCPY)
160 #endif