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"
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
59 #if XTENSA_ESP32_PSRAM_CACHE_FIX
67 .type strncpy, @function
70 /* a2 = dst, a3 = src */
72 mov a10, a2 // leave dst in return value register
73 beqz a4, .Lret // if n is zero
79 bbsi.l a3, 0, .Lsrc1mod2
80 bbsi.l a3, 1, .Lsrc2mod4
83 /* Check if the destination is aligned. */
85 bnone a10, a8, .Laligned
90 /* Fill the dst with zeros -- n is at least 1. */
94 bbsi.l a10, 0, .Lfill1mod2
95 bbsi.l a10, 1, .Lfill2mod4
97 blti a4, 4, .Lfillcleanup
99 /* Loop filling complete words with zero. */
110 #else /* !XCHAL_HAVE_LOOPS */
117 #endif /* !XCHAL_HAVE_LOOPS */
122 /* Fill leftover (1 to 3) bytes with zero. */
123 s8i a9, a10, 0 // store byte 0
124 addi a4, a4, -1 // decrement n
126 bnez a4, .Lfillcleanup
129 #if XTENSA_ESP32_PSRAM_CACHE_FIX
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
152 /* dst is word-aligned; src is word-aligned; n is at least 1. */
156 #if XCHAL_HAVE_DENSITY
157 /* (2 mod 4) alignment for loop instruction */
159 /* (1 mod 4) alignment for loop instruction */
166 #if XCHAL_HAVE_DENSITY
167 _movi.n a8, 0 // set up for the maximum loop count
169 _movi a8, 0 // set up for the maximum loop count
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 */
200 .Lz0: /* Byte 0 is zero. */
205 addi a4, a4, -1 // decrement n
206 addi a10, a10, 1 // advance dst pointer
209 .Lz1: /* Byte 1 is zero. */
214 addi a4, a4, -2 // decrement n
215 addi a10, a10, 2 // advance dst pointer
218 .Lz2: /* Byte 2 is zero. */
225 addi a4, a4, -3 // decrement n
226 addi a10, a10, 3 // advance dst pointer
231 #if XCHAL_HAVE_DENSITY
232 /* (2 mod 4) alignment for loop instruction */
234 /* (1 mod 4) alignment for loop instruction */
242 #if XCHAL_HAVE_DENSITY
243 _movi.n a8, 0 // set up for the maximum loop count
245 _movi a8, 0 // set up for the maximum loop count
247 loop a8, 2f // loop forever (almost anyway)
251 #if XTENSA_ESP32_PSRAM_CACHE_FIX
268 #if XTENSA_ESP32_PSRAM_CACHE_FIX
274 .size strncpy, . - strncpy