]>
Commit | Line | Data |
---|---|---|
2b778ceb | 1 | /* Copyright (C) 1999-2021 Free Software Foundation, Inc. |
3846ef75 UD |
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 | |
41bdb6e2 AJ |
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. | |
3846ef75 UD |
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 | |
41bdb6e2 | 12 | Lesser General Public License for more details. |
3846ef75 | 13 | |
41bdb6e2 | 14 | You should have received a copy of the GNU Lesser General Public |
59ba27a6 | 15 | License along with the GNU C Library; if not, see |
5a82c748 | 16 | <https://www.gnu.org/licenses/>. */ |
3846ef75 UD |
17 | |
18 | #include <sysdep.h> | |
3846ef75 | 19 | |
8439150e UD |
20 | /* void *memcpy(void *dst, const void *src, size_t n); |
21 | No overlap between the memory of DST and of SRC are assumed. */ | |
3846ef75 UD |
22 | |
23 | ENTRY(memcpy) | |
8439150e UD |
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 | |
3846ef75 | 38 | mov.b r1,@r4 |
3846ef75 | 39 | add #1,r4 |
8439150e UD |
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 | |
3ce2865f | 49 | #ifdef __BIG_ENDIAN__ |
3846ef75 | 50 | add #1,r4 |
3846ef75 | 51 | mov.b r1,@r4 |
8439150e UD |
52 | shlr8 r1 |
53 | mov.b r1,@-r4 | |
54 | add #2,r4 | |
55 | #else | |
56 | mov.b r1,@r4 | |
3846ef75 | 57 | add #1,r4 |
8439150e | 58 | shlr8 r1 |
3846ef75 UD |
59 | mov.b r1,@r4 |
60 | add #1,r4 | |
8439150e UD |
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 | |
3846ef75 | 70 | mov r4,r0 |
8439150e | 71 | mov r6,r7 |
3846ef75 | 72 | and #3,r0 |
8439150e UD |
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. */ | |
3ce2865f | 98 | #ifdef __BIG_ENDIAN__ |
8439150e UD |
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 | |
3846ef75 | 139 | mov.l @r5+,r1 |
3ce2865f | 140 | #ifdef __BIG_ENDIAN__ |
8439150e UD |
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 | |
3846ef75 | 158 | add #8,r4 |
8439150e UD |
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 | |
3846ef75 | 190 | add #1,r4 |
8439150e UD |
191 | |
192 | L_exit: | |
193 | rts | |
194 | mov r3,r0 /* Return destination. */ | |
195 | END(memcpy) | |
85dd1003 | 196 | libc_hidden_builtin_def (memcpy) |