blob: fe3ec894cf43de619e359f909d723824af3d6bc2 [file] [log] [blame]
lh9ed821d2023-04-07 01:36:19 -07001/* Optimized strcpy for Xtensa.
2 Copyright (C) 2001, 2007 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, write to the Free
17 Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
18 Boston, MA 02110-1301, USA. */
19
20#include "../../sysdeps/linux/xtensa/sysdep.h"
21#include <bits/xtensa-config.h>
22
23#ifdef __XTENSA_EB__
24#define MASK0 0xff000000
25#define MASK1 0x00ff0000
26#define MASK2 0x0000ff00
27#define MASK3 0x000000ff
28#else
29#define MASK0 0x000000ff
30#define MASK1 0x0000ff00
31#define MASK2 0x00ff0000
32#define MASK3 0xff000000
33#endif
34
35/* Do not use .literal_position in the ENTRY macro. */
36#undef LITERAL_POSITION
37#define LITERAL_POSITION
38
39 .text
40 .align 4
41 .literal_position
42__strncpy_aux:
43
44.Lsrc1mod2: /* src address is odd */
45 l8ui a8, a3, 0 /* get byte 0 */
46 addi a3, a3, 1 /* advance src pointer */
47 s8i a8, a10, 0 /* store byte 0 */
48 addi a4, a4, -1 /* decrement n */
49 beqz a4, .Lret /* if n is zero */
50 addi a10, a10, 1 /* advance dst pointer */
51 beqz a8, .Lfill /* if byte 0 is zero */
52 bbci.l a3, 1, .Lsrcaligned /* if src is now word-aligned */
53
54.Lsrc2mod4: /* src address is 2 mod 4 */
55 l8ui a8, a3, 0 /* get byte 0 */
56 addi a4, a4, -1 /* decrement n */
57 s8i a8, a10, 0 /* store byte 0 */
58 beqz a4, .Lret /* if n is zero */
59 addi a10, a10, 1 /* advance dst pointer */
60 beqz a8, .Lfill /* if byte 0 is zero */
61 l8ui a8, a3, 1 /* get byte 0 */
62 addi a3, a3, 2 /* advance src pointer */
63 s8i a8, a10, 0 /* store byte 0 */
64 addi a4, a4, -1 /* decrement n */
65 beqz a4, .Lret /* if n is zero */
66 addi a10, a10, 1 /* advance dst pointer */
67 bnez a8, .Lsrcaligned
68 j .Lfill
69
70.Lret:
71 retw
72
73
74ENTRY (strncpy)
75 /* a2 = dst, a3 = src */
76
77 mov a10, a2 /* leave dst in return value register */
78 beqz a4, .Lret /* if n is zero */
79
80 movi a11, MASK0
81 movi a5, MASK1
82 movi a6, MASK2
83 movi a7, MASK3
84 bbsi.l a3, 0, .Lsrc1mod2
85 bbsi.l a3, 1, .Lsrc2mod4
86.Lsrcaligned:
87
88 /* Check if the destination is aligned. */
89 movi a8, 3
90 bnone a10, a8, .Laligned
91
92 j .Ldstunaligned
93
94
95/* Fill the dst with zeros -- n is at least 1. */
96
97.Lfill:
98 movi a9, 0
99 bbsi.l a10, 0, .Lfill1mod2
100 bbsi.l a10, 1, .Lfill2mod4
101.Lfillaligned:
102 blti a4, 4, .Lfillcleanup
103
104 /* Loop filling complete words with zero. */
105#if XCHAL_HAVE_LOOPS
106
107 srai a8, a4, 2
108 loop a8, 1f
109 s32i a9, a10, 0
110 addi a10, a10, 4
111
1121: slli a8, a8, 2
113 sub a4, a4, a8
114
115#else /* !XCHAL_HAVE_LOOPS */
116
1171: s32i a9, a10, 0
118 addi a10, a10, 4
119 addi a4, a4, -4
120 bgei a4, 4, 1b
121
122#endif /* !XCHAL_HAVE_LOOPS */
123
124 beqz a4, 2f
125
126.Lfillcleanup:
127 /* Fill leftover (1 to 3) bytes with zero. */
128 s8i a9, a10, 0 /* store byte 0 */
129 addi a4, a4, -1 /* decrement n */
130 addi a10, a10, 1
131 bnez a4, .Lfillcleanup
132
1332: retw
134
135.Lfill1mod2: /* dst address is odd */
136 s8i a9, a10, 0 /* store byte 0 */
137 addi a4, a4, -1 /* decrement n */
138 beqz a4, 2b /* if n is zero */
139 addi a10, a10, 1 /* advance dst pointer */
140 bbci.l a10, 1, .Lfillaligned /* if dst is now word-aligned */
141
142.Lfill2mod4: /* dst address is 2 mod 4 */
143 s8i a9, a10, 0 /* store byte 0 */
144 addi a4, a4, -1 /* decrement n */
145 beqz a4, 2b /* if n is zero */
146 s8i a9, a10, 1 /* store byte 1 */
147 addi a4, a4, -1 /* decrement n */
148 beqz a4, 2b /* if n is zero */
149 addi a10, a10, 2 /* advance dst pointer */
150 j .Lfillaligned
151
152
153/* dst is word-aligned; src is word-aligned; n is at least 1. */
154
155 .align 4
156 /* (2 mod 4) alignment for loop instruction */
157.Laligned:
158#if XCHAL_HAVE_LOOPS
159 _movi.n a8, 0 /* set up for the maximum loop count */
160 loop a8, 1f /* loop forever (almost anyway) */
161 blti a4, 5, .Ldstunaligned /* n is near limit; do one at a time */
162 l32i a8, a3, 0 /* get word from src */
163 addi a3, a3, 4 /* advance src pointer */
164 bnone a8, a11, .Lz0 /* if byte 0 is zero */
165 bnone a8, a5, .Lz1 /* if byte 1 is zero */
166 bnone a8, a6, .Lz2 /* if byte 2 is zero */
167 s32i a8, a10, 0 /* store word to dst */
168 addi a4, a4, -4 /* decrement n */
169 addi a10, a10, 4 /* advance dst pointer */
170 bnone a8, a7, .Lfill /* if byte 3 is zero */
1711:
172
173#else /* !XCHAL_HAVE_LOOPS */
174
1751: blti a4, 5, .Ldstunaligned /* n is near limit; do one at a time */
176 l32i a8, a3, 0 /* get word from src */
177 addi a3, a3, 4 /* advance src pointer */
178 bnone a8, a11, .Lz0 /* if byte 0 is zero */
179 bnone a8, a5, .Lz1 /* if byte 1 is zero */
180 bnone a8, a6, .Lz2 /* if byte 2 is zero */
181 s32i a8, a10, 0 /* store word to dst */
182 addi a4, a4, -4 /* decrement n */
183 addi a10, a10, 4 /* advance dst pointer */
184 bany a8, a7, 1b /* no zeroes */
185#endif /* !XCHAL_HAVE_LOOPS */
186
187 j .Lfill
188
189.Lz0: /* Byte 0 is zero. */
190#ifdef __XTENSA_EB__
191 movi a8, 0
192#endif
193 s8i a8, a10, 0
194 addi a4, a4, -1 /* decrement n */
195 addi a10, a10, 1 /* advance dst pointer */
196 j .Lfill
197
198.Lz1: /* Byte 1 is zero. */
199#ifdef __XTENSA_EB__
200 extui a8, a8, 16, 16
201#endif
202 s16i a8, a10, 0
203 addi a4, a4, -2 /* decrement n */
204 addi a10, a10, 2 /* advance dst pointer */
205 j .Lfill
206
207.Lz2: /* Byte 2 is zero. */
208#ifdef __XTENSA_EB__
209 extui a8, a8, 16, 16
210#endif
211 s16i a8, a10, 0
212 movi a8, 0
213 s8i a8, a10, 2
214 addi a4, a4, -3 /* decrement n */
215 addi a10, a10, 3 /* advance dst pointer */
216 j .Lfill
217
218 .align 4
219 /* (2 mod 4) alignment for loop instruction */
220.Ldstunaligned:
221
222#if XCHAL_HAVE_LOOPS
223 _movi.n a8, 0 /* set up for the maximum loop count */
224 loop a8, 2f /* loop forever (almost anyway) */
225#endif
2261: l8ui a8, a3, 0
227 addi a3, a3, 1
228 s8i a8, a10, 0
229 addi a4, a4, -1
230 beqz a4, 3f
231 addi a10, a10, 1
232#if XCHAL_HAVE_LOOPS
233 beqz a8, 2f
234#else
235 bnez a8, 1b
236#endif
2372: j .Lfill
238
2393: retw
240
241libc_hidden_def (strncpy)