1 /* _memcopy.c -- subroutines for memory copy functions.
2 Copyright (C) 1991-2023 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
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.
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.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <https://www.gnu.org/licenses/>. */
19 /* BE VERY CAREFUL IF YOU CHANGE THIS CODE...! */
22 #include <libc-diag.h>
23 /* Compiling with -O1 might warn that 'a2' and 'a3' may be used
24 uninitialized. There are only two ways to arrive at labels 'do4', 'do3'
25 or 'do1', all of which use 'a2' or 'a3' in the MERGE macro: either from
26 the earlier switch case statement or via a loop iteration. In all cases
27 the switch statement or previous loop sets both 'a2' and 'a3'.
29 Since the usage is within the MERGE macro we disable the
30 warning in the definition, but only in this file. */
31 DIAG_PUSH_NEEDS_COMMENT
;
32 DIAG_IGNORE_NEEDS_COMMENT (6, "-Wmaybe-uninitialized");
34 DIAG_POP_NEEDS_COMMENT
;
36 /* _wordcopy_fwd_aligned -- Copy block beginning at SRCP to
37 block beginning at DSTP with LEN `op_t' words (not LEN bytes!).
38 Both SRCP and DSTP should be aligned for memory operations on `op_t's. */
40 #ifndef WORDCOPY_FWD_ALIGNED
41 # define WORDCOPY_FWD_ALIGNED _wordcopy_fwd_aligned
45 WORDCOPY_FWD_ALIGNED (long int dstp
, long int srcp
, size_t len
)
52 a0
= ((op_t
*) srcp
)[0];
58 a1
= ((op_t
*) srcp
)[0];
64 a0
= ((op_t
*) srcp
)[0];
70 a1
= ((op_t
*) srcp
)[0];
76 a0
= ((op_t
*) srcp
)[0];
82 a1
= ((op_t
*) srcp
)[0];
89 if (OP_T_THRES
<= 3 * OPSIZ
&& len
== 0)
91 a0
= ((op_t
*) srcp
)[0];
96 a1
= ((op_t
*) srcp
)[0];
100 if (OP_T_THRES
<= 3 * OPSIZ
&& len
== 0)
102 goto do8
; /* No-op. */
108 a0
= ((op_t
*) srcp
)[0];
109 /* Compiling with -O1 may warn that 'a1' may be used uninitialized.
110 There are only two ways to arrive at label 'do8' and they are via a
111 do-while loop iteration or directly via the earlier switch 'case 1:'
112 case. The switch case always sets 'a1' and all previous loop
113 iterations will also have set 'a1' before the use. */
114 DIAG_PUSH_NEEDS_COMMENT
;
115 DIAG_IGNORE_NEEDS_COMMENT (6, "-Wmaybe-uninitialized");
116 ((op_t
*) dstp
)[0] = a1
;
117 DIAG_POP_NEEDS_COMMENT
;
119 a1
= ((op_t
*) srcp
)[1];
120 ((op_t
*) dstp
)[1] = a0
;
122 a0
= ((op_t
*) srcp
)[2];
123 ((op_t
*) dstp
)[2] = a1
;
125 a1
= ((op_t
*) srcp
)[3];
126 ((op_t
*) dstp
)[3] = a0
;
128 a0
= ((op_t
*) srcp
)[4];
129 ((op_t
*) dstp
)[4] = a1
;
131 a1
= ((op_t
*) srcp
)[5];
132 ((op_t
*) dstp
)[5] = a0
;
134 a0
= ((op_t
*) srcp
)[6];
135 ((op_t
*) dstp
)[6] = a1
;
137 a1
= ((op_t
*) srcp
)[7];
138 ((op_t
*) dstp
)[7] = a0
;
146 /* This is the right position for do0. Please don't move
149 ((op_t
*) dstp
)[0] = a1
;
152 /* _wordcopy_fwd_dest_aligned -- Copy block beginning at SRCP to
153 block beginning at DSTP with LEN `op_t' words (not LEN bytes!).
154 DSTP should be aligned for memory operations on `op_t's, but SRCP must
157 #ifndef WORDCOPY_FWD_DEST_ALIGNED
158 # define WORDCOPY_FWD_DEST_ALIGNED _wordcopy_fwd_dest_aligned
162 WORDCOPY_FWD_DEST_ALIGNED (long int dstp
, long int srcp
, size_t len
)
167 /* Calculate how to shift a word read at the memory operation
168 aligned srcp to make it aligned for copy. */
170 sh_1
= 8 * (srcp
% OPSIZ
);
171 sh_2
= 8 * OPSIZ
- sh_1
;
173 /* Make SRCP aligned by rounding it down to the beginning of the `op_t'
174 it points in the middle of. */
180 a1
= ((op_t
*) srcp
)[0];
181 a2
= ((op_t
*) srcp
)[1];
187 a0
= ((op_t
*) srcp
)[0];
188 a1
= ((op_t
*) srcp
)[1];
194 if (OP_T_THRES
<= 3 * OPSIZ
&& len
== 0)
196 a3
= ((op_t
*) srcp
)[0];
197 a0
= ((op_t
*) srcp
)[1];
203 a2
= ((op_t
*) srcp
)[0];
204 a3
= ((op_t
*) srcp
)[1];
208 if (OP_T_THRES
<= 3 * OPSIZ
&& len
== 0)
210 goto do4
; /* No-op. */
216 a0
= ((op_t
*) srcp
)[0];
217 ((op_t
*) dstp
)[0] = MERGE (a2
, sh_1
, a3
, sh_2
);
219 a1
= ((op_t
*) srcp
)[1];
220 ((op_t
*) dstp
)[1] = MERGE (a3
, sh_1
, a0
, sh_2
);
222 a2
= ((op_t
*) srcp
)[2];
223 ((op_t
*) dstp
)[2] = MERGE (a0
, sh_1
, a1
, sh_2
);
225 a3
= ((op_t
*) srcp
)[3];
226 ((op_t
*) dstp
)[3] = MERGE (a1
, sh_1
, a2
, sh_2
);
234 /* This is the right position for do0. Please don't move
237 ((op_t
*) dstp
)[0] = MERGE (a2
, sh_1
, a3
, sh_2
);
240 /* _wordcopy_bwd_aligned -- Copy block finishing right before
241 SRCP to block finishing right before DSTP with LEN `op_t' words
242 (not LEN bytes!). Both SRCP and DSTP should be aligned for memory
243 operations on `op_t's. */
245 #ifndef WORDCOPY_BWD_ALIGNED
246 # define WORDCOPY_BWD_ALIGNED _wordcopy_bwd_aligned
250 WORDCOPY_BWD_ALIGNED (long int dstp
, long int srcp
, size_t len
)
259 a0
= ((op_t
*) srcp
)[1];
265 a1
= ((op_t
*) srcp
)[2];
271 a0
= ((op_t
*) srcp
)[3];
277 a1
= ((op_t
*) srcp
)[4];
283 a0
= ((op_t
*) srcp
)[5];
289 a1
= ((op_t
*) srcp
)[6];
294 if (OP_T_THRES
<= 3 * OPSIZ
&& len
== 0)
298 a0
= ((op_t
*) srcp
)[7];
303 a1
= ((op_t
*) srcp
)[8];
305 if (OP_T_THRES
<= 3 * OPSIZ
&& len
== 0)
307 goto do8
; /* No-op. */
313 a0
= ((op_t
*) srcp
)[7];
314 /* Check the comment on WORDCOPY_FWD_ALIGNED. */
315 DIAG_PUSH_NEEDS_COMMENT
;
316 DIAG_IGNORE_NEEDS_COMMENT (6, "-Wmaybe-uninitialized");
317 ((op_t
*) dstp
)[7] = a1
;
318 DIAG_POP_NEEDS_COMMENT
;
320 a1
= ((op_t
*) srcp
)[6];
321 ((op_t
*) dstp
)[6] = a0
;
323 a0
= ((op_t
*) srcp
)[5];
324 ((op_t
*) dstp
)[5] = a1
;
326 a1
= ((op_t
*) srcp
)[4];
327 ((op_t
*) dstp
)[4] = a0
;
329 a0
= ((op_t
*) srcp
)[3];
330 ((op_t
*) dstp
)[3] = a1
;
332 a1
= ((op_t
*) srcp
)[2];
333 ((op_t
*) dstp
)[2] = a0
;
335 a0
= ((op_t
*) srcp
)[1];
336 ((op_t
*) dstp
)[1] = a1
;
338 a1
= ((op_t
*) srcp
)[0];
339 ((op_t
*) dstp
)[0] = a0
;
347 /* This is the right position for do0. Please don't move
350 ((op_t
*) dstp
)[7] = a1
;
353 /* _wordcopy_bwd_dest_aligned -- Copy block finishing right
354 before SRCP to block finishing right before DSTP with LEN `op_t'
355 words (not LEN bytes!). DSTP should be aligned for memory
356 operations on `op_t', but SRCP must *not* be aligned. */
358 #ifndef WORDCOPY_BWD_DEST_ALIGNED
359 # define WORDCOPY_BWD_DEST_ALIGNED _wordcopy_bwd_dest_aligned
363 WORDCOPY_BWD_DEST_ALIGNED (long int dstp
, long int srcp
, size_t len
)
368 /* Calculate how to shift a word read at the memory operation
369 aligned srcp to make it aligned for copy. */
371 sh_1
= 8 * (srcp
% OPSIZ
);
372 sh_2
= 8 * OPSIZ
- sh_1
;
374 /* Make srcp aligned by rounding it down to the beginning of the op_t
375 it points in the middle of. */
384 a2
= ((op_t
*) srcp
)[2];
385 a1
= ((op_t
*) srcp
)[1];
391 a3
= ((op_t
*) srcp
)[3];
392 a2
= ((op_t
*) srcp
)[2];
396 if (OP_T_THRES
<= 3 * OPSIZ
&& len
== 0)
400 a0
= ((op_t
*) srcp
)[4];
401 a3
= ((op_t
*) srcp
)[3];
406 a1
= ((op_t
*) srcp
)[5];
407 a0
= ((op_t
*) srcp
)[4];
409 if (OP_T_THRES
<= 3 * OPSIZ
&& len
== 0)
411 goto do4
; /* No-op. */
417 a3
= ((op_t
*) srcp
)[3];
418 ((op_t
*) dstp
)[3] = MERGE (a0
, sh_1
, a1
, sh_2
);
420 a2
= ((op_t
*) srcp
)[2];
421 ((op_t
*) dstp
)[2] = MERGE (a3
, sh_1
, a0
, sh_2
);
423 a1
= ((op_t
*) srcp
)[1];
424 ((op_t
*) dstp
)[1] = MERGE (a2
, sh_1
, a3
, sh_2
);
426 a0
= ((op_t
*) srcp
)[0];
427 ((op_t
*) dstp
)[0] = MERGE (a1
, sh_1
, a2
, sh_2
);
435 /* This is the right position for do0. Please don't move
438 ((op_t
*) dstp
)[3] = MERGE (a0
, sh_1
, a1
, sh_2
);