1 /* _memcopy.c -- subroutines for memory copy functions.
2    Copyright (C) 1991-2022 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, see
17    <https://www.gnu.org/licenses/>.  */
18 
19 /* BE VERY CAREFUL IF YOU CHANGE THIS CODE...!  */
20 
21 #include <stddef.h>
22 #include <memcopy.h>
23 
24 /* _wordcopy_fwd_aligned -- Copy block beginning at SRCP to
25    block beginning at DSTP with LEN `op_t' words (not LEN bytes!).
26    Both SRCP and DSTP should be aligned for memory operations on `op_t's.  */
27 
28 #ifndef WORDCOPY_FWD_ALIGNED
29 # define WORDCOPY_FWD_ALIGNED _wordcopy_fwd_aligned
30 #endif
31 
32 void
WORDCOPY_FWD_ALIGNED(long int dstp,long int srcp,size_t len)33 WORDCOPY_FWD_ALIGNED (long int dstp, long int srcp, size_t len)
34 {
35   op_t a0, a1;
36 
37   if (len & 1)
38   {
39     ((op_t *) dstp)[0] = ((op_t *) srcp)[0];
40 
41     if (len == 1)
42       return;
43     srcp += OPSIZ;
44     dstp += OPSIZ;
45     len -= 1;
46   }
47 
48   do
49     {
50       a0 = ((op_t *) srcp)[0];
51       a1 = ((op_t *) srcp)[1];
52       ((op_t *) dstp)[0] = a0;
53       ((op_t *) dstp)[1] = a1;
54 
55       srcp += 2 * OPSIZ;
56       dstp += 2 * OPSIZ;
57       len -= 2;
58     }
59   while (len != 0);
60 }
61 
62 /* _wordcopy_fwd_dest_aligned -- Copy block beginning at SRCP to
63    block beginning at DSTP with LEN `op_t' words (not LEN bytes!).
64    DSTP should be aligned for memory operations on `op_t's, but SRCP must
65    *not* be aligned.  */
66 
67 #ifndef WORDCOPY_FWD_DEST_ALIGNED
68 # define WORDCOPY_FWD_DEST_ALIGNED _wordcopy_fwd_dest_aligned
69 #endif
70 
71 void
WORDCOPY_FWD_DEST_ALIGNED(long int dstp,long int srcp,size_t len)72 WORDCOPY_FWD_DEST_ALIGNED (long int dstp, long int srcp, size_t len)
73 {
74   op_t a0, a1, a2;
75   int sh_1, sh_2;
76 
77   /* Calculate how to shift a word read at the memory operation
78      aligned srcp to make it aligned for copy.  */
79 
80   sh_1 = 8 * (srcp % OPSIZ);
81   sh_2 = 8 * OPSIZ - sh_1;
82 
83   /* Make SRCP aligned by rounding it down to the beginning of the `op_t'
84      it points in the middle of.  */
85   srcp &= -OPSIZ;
86   a0 = ((op_t *) srcp)[0];
87 
88   if (len & 1)
89   {
90     a1 = ((op_t *) srcp)[1];
91     ((op_t *) dstp)[0] = MERGE (a0, sh_1, a1, sh_2);
92 
93     if (len == 1)
94       return;
95 
96     a0 = a1;
97     srcp += OPSIZ;
98     dstp += OPSIZ;
99     len -= 1;
100   }
101 
102   do
103     {
104       a1 = ((op_t *) srcp)[1];
105       a2 = ((op_t *) srcp)[2];
106       ((op_t *) dstp)[0] = MERGE (a0, sh_1, a1, sh_2);
107       ((op_t *) dstp)[1] = MERGE (a1, sh_1, a2, sh_2);
108       a0 = a2;
109 
110       srcp += 2 * OPSIZ;
111       dstp += 2 * OPSIZ;
112       len -= 2;
113     }
114   while (len != 0);
115 }
116 
117 /* _wordcopy_bwd_aligned -- Copy block finishing right before
118    SRCP to block finishing right before DSTP with LEN `op_t' words
119    (not LEN bytes!).  Both SRCP and DSTP should be aligned for memory
120    operations on `op_t's.  */
121 
122 #ifndef WORDCOPY_BWD_ALIGNED
123 # define WORDCOPY_BWD_ALIGNED _wordcopy_bwd_aligned
124 #endif
125 
126 void
WORDCOPY_BWD_ALIGNED(long int dstp,long int srcp,size_t len)127 WORDCOPY_BWD_ALIGNED (long int dstp, long int srcp, size_t len)
128 {
129   op_t a0, a1;
130 
131   if (len & 1)
132   {
133     srcp -= OPSIZ;
134     dstp -= OPSIZ;
135     ((op_t *) dstp)[0] = ((op_t *) srcp)[0];
136 
137     if (len == 1)
138       return;
139     len -= 1;
140   }
141 
142   do
143     {
144       srcp -= 2 * OPSIZ;
145       dstp -= 2 * OPSIZ;
146 
147       a1 = ((op_t *) srcp)[1];
148       a0 = ((op_t *) srcp)[0];
149       ((op_t *) dstp)[1] = a1;
150       ((op_t *) dstp)[0] = a0;
151 
152       len -= 2;
153     }
154   while (len != 0);
155 }
156 
157 /* _wordcopy_bwd_dest_aligned -- Copy block finishing right
158    before SRCP to block finishing right before DSTP with LEN `op_t'
159    words (not LEN bytes!).  DSTP should be aligned for memory
160    operations on `op_t', but SRCP must *not* be aligned.  */
161 
162 #ifndef WORDCOPY_BWD_DEST_ALIGNED
163 # define WORDCOPY_BWD_DEST_ALIGNED _wordcopy_bwd_dest_aligned
164 #endif
165 
166 void
WORDCOPY_BWD_DEST_ALIGNED(long int dstp,long int srcp,size_t len)167 WORDCOPY_BWD_DEST_ALIGNED (long int dstp, long int srcp, size_t len)
168 {
169   op_t a0, a1, a2;
170   int sh_1, sh_2;
171 
172   /* Calculate how to shift a word read at the memory operation
173      aligned srcp to make it aligned for copy.  */
174 
175   sh_1 = 8 * (srcp % OPSIZ);
176   sh_2 = 8 * OPSIZ - sh_1;
177 
178   /* Make srcp aligned by rounding it down to the beginning of the op_t
179      it points in the middle of.  */
180   srcp &= -OPSIZ;
181   a2 = ((op_t *) srcp)[0];
182 
183   if (len & 1)
184   {
185     srcp -= OPSIZ;
186     dstp -= OPSIZ;
187     a1 = ((op_t *) srcp)[0];
188     ((op_t *) dstp)[0] = MERGE (a1, sh_1, a2, sh_2);
189 
190     if (len == 1)
191       return;
192 
193     a2 = a1;
194     len -= 1;
195   }
196 
197   do
198     {
199       srcp -= 2 * OPSIZ;
200       dstp -= 2 * OPSIZ;
201 
202       a1 = ((op_t *) srcp)[1];
203       a0 = ((op_t *) srcp)[0];
204       ((op_t *) dstp)[1] = MERGE (a1, sh_1, a2, sh_2);
205       ((op_t *) dstp)[0] = MERGE (a0, sh_1, a1, sh_2);
206       a2 = a0;
207 
208       len -= 2;
209     }
210   while (len != 0);
211 }
212