Cygwin: access: Fix X_OK behaviour for backup operators and admins
[newlib-cygwin.git] / newlib / libc / machine / xtensa / strncpy.S
blobfaa7c7b256e0eea9f5abe9089658f395e918c9bb
1 /* ANSI C standard library function strncpy.
3    Copyright (c) 2001-2008 Tensilica Inc.
5    Permission is hereby granted, free of charge, to any person obtaining
6    a copy of this software and associated documentation files (the
7    "Software"), to deal in the Software without restriction, including
8    without limitation the rights to use, copy, modify, merge, publish,
9    distribute, sublicense, and/or sell copies of the Software, and to
10    permit persons to whom the Software is furnished to do so, subject to
11    the following conditions:
13    The above copyright notice and this permission notice shall be included
14    in all copies or substantial portions of the Software.
16    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19    IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20    CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21    TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22    SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
24 #include "xtensa-asm.h"
26         .text
27 .begin schedule
28         .align  4
29         .literal_position
30 __strncpy_aux:
32 .Lsrc1mod2: // src address is odd
33         l8ui    a8, a3, 0       // get byte 0
34         addi    a3, a3, 1       // advance src pointer
35         s8i     a8, a10, 0      // store byte 0
36         addi    a4, a4, -1      // decrement n
37         beqz    a4, .Lret       // if n is zero
38         addi    a10, a10, 1     // advance dst pointer
39         beqz    a8, .Lfill      // if byte 0 is zero
40         bbci.l  a3, 1, .Lsrcaligned // if src is now word-aligned
42 .Lsrc2mod4: // src address is 2 mod 4
43         l8ui    a8, a3, 0       // get byte 0
44         addi    a4, a4, -1      // decrement n
45         s8i     a8, a10, 0      // store byte 0
46         beqz    a4, .Lret       // if n is zero
47         addi    a10, a10, 1     // advance dst pointer
48         beqz    a8, .Lfill      // if byte 0 is zero
49         l8ui    a8, a3, 1       // get byte 0
50         addi    a3, a3, 2       // advance src pointer
51         s8i     a8, a10, 0      // store byte 0
52         addi    a4, a4, -1      // decrement n
53         beqz    a4, .Lret       // if n is zero
54         addi    a10, a10, 1     // advance dst pointer
55         bnez    a8, .Lsrcaligned
56         j       .Lfill
58 .Lret:
59 #if XTENSA_ESP32_PSRAM_CACHE_FIX
60         memw
61 #endif
62         leaf_return
65         .align  4
66         .global strncpy
67         .type   strncpy, @function
68 strncpy:
69         leaf_entry sp, 16
70         /* a2 = dst, a3 = src */
72         mov     a10, a2         // leave dst in return value register
73         beqz    a4, .Lret       // if n is zero
75         movi    a11, MASK0
76         movi    a5, MASK1
77         movi    a6, MASK2
78         movi    a7, MASK3
79         bbsi.l  a3, 0, .Lsrc1mod2
80         bbsi.l  a3, 1, .Lsrc2mod4
81 .Lsrcaligned:
83         /* Check if the destination is aligned.  */
84         movi    a8, 3
85         bnone   a10, a8, .Laligned
87         j       .Ldstunaligned
90 /* Fill the dst with zeros -- n is at least 1.  */
92 .Lfill:
93         movi    a9, 0
94         bbsi.l  a10, 0, .Lfill1mod2
95         bbsi.l  a10, 1, .Lfill2mod4
96 .Lfillaligned:
97         blti    a4, 4, .Lfillcleanup
99         /* Loop filling complete words with zero.  */
100 #if XCHAL_HAVE_LOOPS
102         srai    a8, a4, 2
103         loop    a8, 1f
104         s32i    a9, a10, 0
105         addi    a10, a10, 4
107 1:      slli    a8, a8, 2
108         sub     a4, a4, a8
110 #else /* !XCHAL_HAVE_LOOPS */
112 1:      s32i    a9, a10, 0
113         addi    a10, a10, 4
114         addi    a4, a4, -4
115         bgei    a4, 4, 1b
117 #endif /* !XCHAL_HAVE_LOOPS */
119         beqz    a4, 2f
121 .Lfillcleanup:
122         /* Fill leftover (1 to 3) bytes with zero.  */
123         s8i     a9, a10, 0      // store byte 0
124         addi    a4, a4, -1      // decrement n
125         addi    a10, a10, 1
126         bnez    a4, .Lfillcleanup
129 #if XTENSA_ESP32_PSRAM_CACHE_FIX
130         memw
131 #endif
132         leaf_return
134 .Lfill1mod2: // dst address is odd
135         s8i     a9, a10, 0      // store byte 0
136         addi    a4, a4, -1      // decrement n
137         beqz    a4, 2b          // if n is zero
138         addi    a10, a10, 1     // advance dst pointer
139         bbci.l  a10, 1, .Lfillaligned // if dst is now word-aligned
141 .Lfill2mod4: // dst address is 2 mod 4
142         s8i     a9, a10, 0      // store byte 0
143         addi    a4, a4, -1      // decrement n
144         beqz    a4, 2b          // if n is zero
145         s8i     a9, a10, 1      // store byte 1
146         addi    a4, a4, -1      // decrement n
147         beqz    a4, 2b          // if n is zero
148         addi    a10, a10, 2     // advance dst pointer
149         j       .Lfillaligned
152 /* dst is word-aligned; src is word-aligned; n is at least 1.  */
154         .align  4
155 #if XCHAL_HAVE_LOOPS
156 #if XCHAL_HAVE_DENSITY
157         /* (2 mod 4) alignment for loop instruction */
158 #else
159         /* (1 mod 4) alignment for loop instruction */
160         .byte   0
161         .byte   0
162 #endif
163 #endif
164 .Laligned:
165 #if XCHAL_HAVE_LOOPS
166 #if XCHAL_HAVE_DENSITY
167         _movi.n a8, 0           // set up for the maximum loop count
168 #else
169         _movi   a8, 0           // set up for the maximum loop count
170 #endif
171         loop    a8, 1f          // loop forever (almost anyway)
172         blti    a4, 5, .Ldstunaligned // n is near limit; do one at a time
173         l32i    a8, a3, 0       // get word from src
174         addi    a3, a3, 4       // advance src pointer
175         bnone   a8, a11, .Lz0   // if byte 0 is zero
176         bnone   a8, a5, .Lz1    // if byte 1 is zero
177         bnone   a8, a6, .Lz2    // if byte 2 is zero
178         s32i    a8, a10, 0      // store word to dst
179         addi    a4, a4, -4      // decrement n
180         addi    a10, a10, 4     // advance dst pointer
181         bnone   a8, a7, .Lfill  // if byte 3 is zero
184 #else /* !XCHAL_HAVE_LOOPS */
186 1:      blti    a4, 5, .Ldstunaligned // n is near limit; do one at a time
187         l32i    a8, a3, 0       // get word from src
188         addi    a3, a3, 4       // advance src pointer
189         bnone   a8, a11, .Lz0   // if byte 0 is zero
190         bnone   a8, a5, .Lz1    // if byte 1 is zero
191         bnone   a8, a6, .Lz2    // if byte 2 is zero
192         s32i    a8, a10, 0      // store word to dst
193         addi    a4, a4, -4      // decrement n
194         addi    a10, a10, 4     // advance dst pointer
195         bany    a8, a7, 1b      // no zeroes
196 #endif /* !XCHAL_HAVE_LOOPS */
198         j       .Lfill
200 .Lz0:   /* Byte 0 is zero.  */
201 #ifdef __XTENSA_EB__
202         movi    a8, 0
203 #endif
204         s8i     a8, a10, 0
205         addi    a4, a4, -1      // decrement n
206         addi    a10, a10, 1     // advance dst pointer
207         j       .Lfill
209 .Lz1:   /* Byte 1 is zero.  */
210 #ifdef __XTENSA_EB__
211         extui   a8, a8, 16, 16
212 #endif
213         s16i    a8, a10, 0
214         addi    a4, a4, -2      // decrement n
215         addi    a10, a10, 2     // advance dst pointer
216         j       .Lfill
218 .Lz2:   /* Byte 2 is zero.  */
219 #ifdef __XTENSA_EB__
220         extui   a8, a8, 16, 16
221 #endif
222         s16i    a8, a10, 0
223         movi    a8, 0
224         s8i     a8, a10, 2
225         addi    a4, a4, -3      // decrement n
226         addi    a10, a10, 3     // advance dst pointer
227         j       .Lfill
229         .align  4
230 #if XCHAL_HAVE_LOOPS
231 #if XCHAL_HAVE_DENSITY
232         /* (2 mod 4) alignment for loop instruction */
233 #else
234         /* (1 mod 4) alignment for loop instruction */
235         .byte   0
236         .byte   0
237 #endif
238 #endif
239 .Ldstunaligned:
241 #if XCHAL_HAVE_LOOPS
242 #if XCHAL_HAVE_DENSITY
243         _movi.n a8, 0           // set up for the maximum loop count
244 #else
245         _movi   a8, 0           // set up for the maximum loop count
246 #endif
247         loop    a8, 2f          // loop forever (almost anyway)
248 #endif
249 1:      l8ui    a8, a3, 0
250         addi    a3, a3, 1
251 #if XTENSA_ESP32_PSRAM_CACHE_FIX
252         nop
253         nop
254         nop
255 #endif
256         s8i     a8, a10, 0
257         addi    a4, a4, -1
258         beqz    a4, 3f
259         addi    a10, a10, 1
260 #if XCHAL_HAVE_LOOPS
261         beqz    a8, 2f
262 #else
263         bnez    a8, 1b
264 #endif
265 2:      j       .Lfill
268 #if XTENSA_ESP32_PSRAM_CACHE_FIX
269         memw
270 #endif
271         leaf_return
272 .end schedule
274         .size   strncpy, . - strncpy