1 | /* Copyright (C) 1999-2022 Free Software Foundation, Inc. |
2 | This file is part of the GNU C Library. |
3 | |
4 | The GNU C Library is free software; you can redistribute it and/or |
5 | modify it under the terms of the GNU Lesser General Public |
6 | License as published by the Free Software Foundation; either |
7 | version 2.1 of the License, or (at your option) any later version. |
8 | |
9 | The GNU C Library is distributed in the hope that it will be useful, |
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
12 | Lesser General Public License for more details. |
13 | |
14 | You should have received a copy of the GNU Lesser General Public |
15 | License along with the GNU C Library; if not, see |
16 | <https://www.gnu.org/licenses/>. */ |
17 | |
18 | #include <sysdep.h> |
19 | |
20 | /* void *memcpy(void *dst, const void *src, size_t n); |
21 | No overlap between the memory of DST and of SRC are assumed. */ |
22 | |
23 | ENTRY(memcpy) |
24 | mov r4,r3 /* Save destination. */ |
25 | |
26 | /* If less than 11 bytes, just do a byte copy. */ |
27 | mov #11,r0 |
28 | cmp/gt r6,r0 |
29 | bt L_byteloop_init |
30 | |
31 | /* Check if we need to word-align source. */ |
32 | mov r5,r0 |
33 | tst #1,r0 |
34 | bt L_wordalign |
35 | |
36 | mov.b @r0+,r1 /* Copy one byte. */ |
37 | add #-1,r6 |
38 | mov.b r1,@r4 |
39 | add #1,r4 |
40 | |
41 | .balignw 4,0x0009 |
42 | L_wordalign: |
43 | /* Check if we need to longword-align source. */ |
44 | tst #2,r0 |
45 | bt L_copy |
46 | |
47 | mov.w @r0+,r1 /* Copy one word. */ |
48 | add #-2,r6 |
49 | #ifdef __BIG_ENDIAN__ |
50 | add #1,r4 |
51 | mov.b r1,@r4 |
52 | shlr8 r1 |
53 | mov.b r1,@-r4 |
54 | add #2,r4 |
55 | #else |
56 | mov.b r1,@r4 |
57 | add #1,r4 |
58 | shlr8 r1 |
59 | mov.b r1,@r4 |
60 | add #1,r4 |
61 | #endif |
62 | L_copy: |
63 | mov r0,r5 |
64 | |
65 | /* Calculate the correct routine to handle the destination |
66 | alignment and simultaneously calculate the loop counts for |
67 | both the 2 word copy loop and byte copy loop. */ |
68 | mova L_jumptable,r0 |
69 | mov r0,r1 |
70 | mov r4,r0 |
71 | mov r6,r7 |
72 | and #3,r0 |
73 | shlr2 r7 |
74 | shll r0 |
75 | shlr r7 |
76 | mov.w @(r0,r1),r2 |
77 | mov #7,r0 |
78 | braf r2 |
79 | and r0,r6 |
80 | L_base: |
81 | |
82 | .balign 4 |
83 | L_jumptable: |
84 | .word L_copydest0 - L_base |
85 | .word L_copydest1_or_3 - L_base |
86 | .word L_copydest2 - L_base |
87 | .word L_copydest1_or_3 - L_base |
88 | |
89 | .balign 4 |
90 | /* Copy routine for (dest mod 4) == 1 or == 3. */ |
91 | L_copydest1_or_3: |
92 | add #-1,r4 |
93 | .balignw 4,0x0009 |
94 | L_copydest1_or_3_loop: |
95 | mov.l @r5+,r0 /* Read first longword. */ |
96 | dt r7 |
97 | mov.l @r5+,r1 /* Read second longword. */ |
98 | #ifdef __BIG_ENDIAN__ |
99 | /* Write first longword as byte, word, byte. */ |
100 | mov.b r0,@(4,r4) |
101 | shlr8 r0 |
102 | mov.w r0,@(2,r4) |
103 | shlr16 r0 |
104 | mov.b r0,@(1,r4) |
105 | mov r1,r0 |
106 | /* Write second longword as byte, word, byte. */ |
107 | mov.b r0,@(8,r4) |
108 | shlr8 r0 |
109 | mov.w r0,@(6,r4) |
110 | shlr16 r0 |
111 | mov.b r0,@(5,r4) |
112 | #else |
113 | /* Write first longword as byte, word, byte. */ |
114 | mov.b r0,@(1,r4) |
115 | shlr8 r0 |
116 | mov.w r0,@(2,r4) |
117 | shlr16 r0 |
118 | mov.b r0,@(4,r4) |
119 | mov r1,r0 |
120 | /* Write second longword as byte, word, byte. */ |
121 | mov.b r0,@(5,r4) |
122 | shlr8 r0 |
123 | mov.w r0,@(6,r4) |
124 | shlr16 r0 |
125 | mov.b r0,@(8,r4) |
126 | #endif |
127 | bf/s L_copydest1_or_3_loop |
128 | add #8,r4 |
129 | |
130 | bra L_byteloop_init |
131 | add #1,r4 |
132 | |
133 | .balign 4 |
134 | /* Copy routine for (dest mod 4) == 2. */ |
135 | L_copydest2: |
136 | L_copydest2_loop: |
137 | mov.l @r5+,r0 |
138 | dt r7 |
139 | mov.l @r5+,r1 |
140 | #ifdef __BIG_ENDIAN__ |
141 | mov.w r0,@(2,r4) |
142 | shlr16 r0 |
143 | mov.w r0,@r4 |
144 | mov r1,r0 |
145 | mov.w r0,@(6,r4) |
146 | shlr16 r0 |
147 | mov.w r0,@(4,r4) |
148 | #else |
149 | mov.w r0,@r4 |
150 | shlr16 r0 |
151 | mov.w r0,@(2,r4) |
152 | mov r1,r0 |
153 | mov.w r0,@(4,r4) |
154 | shlr16 r0 |
155 | mov.w r0,@(6,r4) |
156 | #endif |
157 | bf/s L_copydest2_loop |
158 | add #8,r4 |
159 | |
160 | bra L_byteloop_init |
161 | nop |
162 | |
163 | .balign 4 |
164 | /* Copy routine for (dest mod 4) == 0. */ |
165 | L_copydest0: |
166 | add #-8,r4 |
167 | .balignw 4,0x0009 |
168 | L_copydest0_loop: |
169 | mov.l @r5+,r0 |
170 | dt r7 |
171 | mov.l @r5+,r1 |
172 | add #8,r4 |
173 | mov.l r0,@r4 |
174 | bf/s L_copydest0_loop |
175 | mov.l r1,@(4,r4) |
176 | |
177 | add #8,r4 /* Fall through. */ |
178 | |
179 | L_byteloop_init: |
180 | tst r6,r6 |
181 | bt L_exit |
182 | |
183 | .balignw 4,0x0009 |
184 | /* Copy remaining bytes. */ |
185 | L_byteloop: |
186 | mov.b @r5+,r0 |
187 | dt r6 |
188 | mov.b r0,@r4 |
189 | bf/s L_byteloop |
190 | add #1,r4 |
191 | |
192 | L_exit: |
193 | rts |
194 | mov r3,r0 /* Return destination. */ |
195 | END(memcpy) |
196 | libc_hidden_builtin_def (memcpy) |
197 | |