OSDN Git Service

Add support for the Meta architecture
[uclinux-h8/uClibc.git] / libc / string / metag / memmove.S
1 !    Copyright (C) 2013 Imagination Technologies Ltd.
2
3 !    Licensed under LGPL v2.1 or later, see the file COPYING.LIB in this tarball.
4
5
6         .text
7         .global _memmove
8         .type   _memmove,function
9 ! D1Ar1 dst
10 ! D0Ar2 src
11 ! D1Ar3 cnt
12 ! D0Re0 dst
13 _memmove:
14         CMP     D1Ar3, #0
15         MOV     D0Re0, D1Ar1
16         BZ      $LEND2
17         MSETL   [A0StP], D0.5, D0.6, D0.7
18         MOV     D1Ar5, D0Ar2
19         CMP     D1Ar1, D1Ar5
20         BLT     $Lforwards_copy
21         SUB     D0Ar4, D1Ar1, D1Ar3
22         ADD     D0Ar4, D0Ar4, #1
23         CMP     D0Ar2, D0Ar4
24         BLT     $Lforwards_copy
25         ! should copy backwards
26         MOV     D1Re0, D0Ar2
27         ! adjust pointer to the end of mem
28         ADD     D0Ar2, D1Re0, D1Ar3
29         ADD     D1Ar1, D1Ar1, D1Ar3
30
31         MOV     A1.2, D0Ar2
32         MOV     A0.2, D1Ar1
33         CMP     D1Ar3, #8
34         BLT     $Lbbyte_loop
35
36         MOV     D0Ar4, D0Ar2
37         MOV     D1Ar5, D1Ar1
38
39         ! test 8 byte alignment
40         ANDS    D1Ar5, D1Ar5, #7
41         BNE     $Lbdest_unaligned
42
43         ANDS    D0Ar4, D0Ar4, #7
44         BNE     $Lbsrc_unaligned
45
46         LSR     D1Ar5, D1Ar3, #3
47
48 $Lbaligned_loop:
49         GETL    D0Re0, D1Re0, [--A1.2]
50         SETL    [--A0.2], D0Re0, D1Re0
51         SUBS    D1Ar5, D1Ar5, #1
52         BNE     $Lbaligned_loop
53
54         ANDS    D1Ar3, D1Ar3, #7
55         BZ      $Lbbyte_loop_exit
56 $Lbbyte_loop:
57         GETB    D1Re0, [--A1.2]
58         SETB    [--A0.2], D1Re0
59         SUBS    D1Ar3, D1Ar3, #1
60         BNE     $Lbbyte_loop
61 $Lbbyte_loop_exit:
62         MOV     D0Re0, A0.2
63 $LEND:
64         SUB     A0.2, A0StP, #24
65         MGETL   D0.5, D0.6, D0.7, [A0.2]
66         SUB     A0StP, A0StP, #24
67 $LEND2:
68         MOV     PC, D1RtP
69
70 $Lbdest_unaligned:
71         GETB    D0Re0, [--A1.2]
72         SETB    [--A0.2], D0Re0
73         SUBS    D1Ar5, D1Ar5, #1
74         SUB     D1Ar3, D1Ar3, #1
75         BNE     $Lbdest_unaligned
76         CMP     D1Ar3, #8
77         BLT     $Lbbyte_loop
78 $Lbsrc_unaligned:
79         LSR     D1Ar5, D1Ar3, #3
80         ! adjust A1.2
81         MOV     D0Ar4, A1.2
82         ! save original address
83         MOV     D0Ar6, A1.2
84
85         ADD     D0Ar4, D0Ar4, #7
86         ANDMB   D0Ar4, D0Ar4, #0xfff8
87         ! new address is the 8-byte aligned one above the original
88         MOV     A1.2, D0Ar4
89
90         ! A0.2 dst 64-bit is aligned
91         ! measure the gap size
92         SUB     D0Ar6, D0Ar4, D0Ar6
93         MOVS    D0Ar4, D0Ar6
94         ! keep this information for the later adjustment
95         ! both aligned
96         BZ      $Lbaligned_loop
97
98         ! prefetch
99         GETL    D0Re0, D1Re0, [--A1.2]
100
101         CMP     D0Ar6, #4
102         BLT     $Lbunaligned_1_2_3
103         ! 32-bit aligned
104         BZ      $Lbaligned_4
105
106         SUB     D0Ar6, D0Ar6, #4
107         ! D1.6 stores the gap size in bits
108         MULW    D1.6, D0Ar6, #8
109         MOV     D0.6, #32
110         ! D0.6 stores the complement of the gap size
111         SUB     D0.6, D0.6, D1.6
112
113 $Lbunaligned_5_6_7:
114         GETL    D0.7, D1.7, [--A1.2]
115         ! form 64-bit data in D0Re0, D1Re0
116         MOV     D1Re0, D0Re0
117         ! D1Re0 << gap-size
118         LSL     D1Re0, D1Re0, D1.6
119         MOV     D0Re0, D1.7
120         ! D0Re0 >> complement
121         LSR     D0Re0, D0Re0, D0.6
122         MOV     D1.5, D0Re0
123         ! combine the both
124         ADD     D1Re0, D1Re0, D1.5
125
126         MOV     D1.5, D1.7
127         LSL     D1.5, D1.5, D1.6
128         MOV     D0Re0, D0.7
129         LSR     D0Re0, D0Re0, D0.6
130         MOV     D0.5, D1.5
131         ADD     D0Re0, D0Re0, D0.5
132
133         SETL    [--A0.2], D0Re0, D1Re0
134         MOV     D0Re0, D0.7
135         MOV     D1Re0, D1.7
136         SUBS    D1Ar5, D1Ar5, #1
137         BNE     $Lbunaligned_5_6_7
138
139         ANDS    D1Ar3, D1Ar3, #7
140         BZ      $Lbbyte_loop_exit
141         ! Adjust A1.2
142         ! A1.2 <- A1.2 +8 - gapsize
143         ADD     A1.2, A1.2, #8
144         SUB     A1.2, A1.2, D0Ar4
145         B       $Lbbyte_loop
146
147 $Lbunaligned_1_2_3:
148         MULW    D1.6, D0Ar6, #8
149         MOV     D0.6, #32
150         SUB     D0.6, D0.6, D1.6
151
152 $Lbunaligned_1_2_3_loop:
153         GETL    D0.7, D1.7, [--A1.2]
154         ! form 64-bit data in D0Re0, D1Re0
155         LSL     D1Re0, D1Re0, D1.6
156         ! save D0Re0 for later use
157         MOV     D0.5, D0Re0
158         LSR     D0Re0, D0Re0, D0.6
159         MOV     D1.5, D0Re0
160         ADD     D1Re0, D1Re0, D1.5
161
162         ! orignal data in D0Re0
163         MOV     D1.5, D0.5
164         LSL     D1.5, D1.5, D1.6
165         MOV     D0Re0, D1.7
166         LSR     D0Re0, D0Re0, D0.6
167         MOV     D0.5, D1.5
168         ADD     D0Re0, D0Re0, D0.5
169
170         SETL    [--A0.2], D0Re0, D1Re0
171         MOV     D0Re0, D0.7
172         MOV     D1Re0, D1.7
173         SUBS    D1Ar5, D1Ar5, #1
174         BNE     $Lbunaligned_1_2_3_loop
175
176         ANDS    D1Ar3, D1Ar3, #7
177         BZ      $Lbbyte_loop_exit
178         ! Adjust A1.2
179         ADD     A1.2, A1.2, #8
180         SUB     A1.2, A1.2, D0Ar4
181         B       $Lbbyte_loop
182
183 $Lbaligned_4:
184         GETL    D0.7, D1.7, [--A1.2]
185         MOV     D1Re0, D0Re0
186         MOV     D0Re0, D1.7
187         SETL    [--A0.2], D0Re0, D1Re0
188         MOV     D0Re0, D0.7
189         MOV     D1Re0, D1.7
190         SUBS    D1Ar5, D1Ar5, #1
191         BNE     $Lbaligned_4
192         ANDS    D1Ar3, D1Ar3, #7
193         BZ      $Lbbyte_loop_exit
194         ! Adjust A1.2
195         ADD     A1.2, A1.2, #8
196         SUB     A1.2, A1.2, D0Ar4
197         B       $Lbbyte_loop
198
199 $Lforwards_copy:
200         MOV     A1.2, D0Ar2
201         MOV     A0.2, D1Ar1
202         CMP     D1Ar3, #8
203         BLT     $Lfbyte_loop
204
205         MOV     D0Ar4, D0Ar2
206         MOV     D1Ar5, D1Ar1
207
208         ANDS    D1Ar5, D1Ar5, #7
209         BNE     $Lfdest_unaligned
210
211         ANDS    D0Ar4, D0Ar4, #7
212         BNE     $Lfsrc_unaligned
213
214         LSR     D1Ar5, D1Ar3, #3
215
216 $Lfaligned_loop:
217         GETL    D0Re0, D1Re0, [A1.2++]
218         SUBS    D1Ar5, D1Ar5, #1
219         SETL    [A0.2++], D0Re0, D1Re0
220         BNE     $Lfaligned_loop
221
222         ANDS    D1Ar3, D1Ar3, #7
223         BZ      $Lfbyte_loop_exit
224 $Lfbyte_loop:
225         GETB    D1Re0, [A1.2++]
226         SETB    [A0.2++], D1Re0
227         SUBS    D1Ar3, D1Ar3, #1
228         BNE     $Lfbyte_loop
229 $Lfbyte_loop_exit:
230         MOV     D0Re0, D1Ar1
231         B       $LEND
232
233 $Lfdest_unaligned:
234         GETB    D0Re0, [A1.2++]
235         ADD     D1Ar5, D1Ar5, #1
236         SUB     D1Ar3, D1Ar3, #1
237         SETB    [A0.2++], D0Re0
238         CMP     D1Ar5, #8
239         BNE     $Lfdest_unaligned
240         CMP     D1Ar3, #8
241         BLT     $Lfbyte_loop
242 $Lfsrc_unaligned:
243         ! adjust A1.2
244         LSR     D1Ar5, D1Ar3, #3
245
246         MOV     D0Ar4, A1.2
247         MOV     D0Ar6, A1.2
248         ANDMB   D0Ar4, D0Ar4, #0xfff8
249         MOV     A1.2, D0Ar4
250
251         ! A0.2 dst 64-bit is aligned
252         SUB     D0Ar6, D0Ar6, D0Ar4
253         ! keep the information for the later adjustment
254         MOVS    D0Ar4, D0Ar6
255
256         ! both aligned
257         BZ      $Lfaligned_loop
258
259         ! prefetch
260         GETL    D0Re0, D1Re0, [A1.2]
261
262         CMP     D0Ar6, #4
263         BLT     $Lfunaligned_1_2_3
264         BZ      $Lfaligned_4
265
266         SUB     D0Ar6, D0Ar6, #4
267         MULW    D0.6, D0Ar6, #8
268         MOV     D1.6, #32
269         SUB     D1.6, D1.6, D0.6
270
271 $Lfunaligned_5_6_7:
272         GETL    D0.7, D1.7, [++A1.2]
273         ! form 64-bit data in D0Re0, D1Re0
274         MOV     D0Re0, D1Re0
275         LSR     D0Re0, D0Re0, D0.6
276         MOV     D1Re0, D0.7
277         LSL     D1Re0, D1Re0, D1.6
278         MOV     D0.5, D1Re0
279         ADD     D0Re0, D0Re0, D0.5
280
281         MOV     D0.5, D0.7
282         LSR     D0.5, D0.5, D0.6
283         MOV     D1Re0, D1.7
284         LSL     D1Re0, D1Re0, D1.6
285         MOV     D1.5, D0.5
286         ADD     D1Re0, D1Re0, D1.5
287
288         SETL    [A0.2++], D0Re0, D1Re0
289         MOV     D0Re0, D0.7
290         MOV     D1Re0, D1.7
291         SUBS    D1Ar5, D1Ar5, #1
292         BNE     $Lfunaligned_5_6_7
293
294         ANDS    D1Ar3, D1Ar3, #7
295         BZ      $Lfbyte_loop_exit
296         ! Adjust A1.2
297         ADD     A1.2, A1.2, D0Ar4
298         B       $Lfbyte_loop
299
300 $Lfunaligned_1_2_3:
301         MULW    D0.6, D0Ar6, #8
302         MOV     D1.6, #32
303         SUB     D1.6, D1.6, D0.6
304
305 $Lfunaligned_1_2_3_loop:
306         GETL    D0.7, D1.7, [++A1.2]
307         ! form 64-bit data in D0Re0, D1Re0
308         LSR     D0Re0, D0Re0, D0.6
309         MOV     D1.5, D1Re0
310         LSL     D1Re0, D1Re0, D1.6
311         MOV     D0.5, D1Re0
312         ADD     D0Re0, D0Re0, D0.5
313
314         MOV     D0.5, D1.5
315         LSR     D0.5, D0.5, D0.6
316         MOV     D1Re0, D0.7
317         LSL     D1Re0, D1Re0, D1.6
318         MOV     D1.5, D0.5
319         ADD     D1Re0, D1Re0, D1.5
320
321         SETL    [A0.2++], D0Re0, D1Re0
322         MOV     D0Re0, D0.7
323         MOV     D1Re0, D1.7
324         SUBS    D1Ar5, D1Ar5, #1
325         BNE     $Lfunaligned_1_2_3_loop
326
327         ANDS    D1Ar3, D1Ar3, #7
328         BZ      $Lfbyte_loop_exit
329         ! Adjust A1.2
330         ADD     A1.2, A1.2, D0Ar4
331         B       $Lfbyte_loop
332
333 $Lfaligned_4:
334         GETL    D0.7, D1.7, [++A1.2]
335         MOV     D0Re0, D1Re0
336         MOV     D1Re0, D0.7
337         SETL    [A0.2++], D0Re0, D1Re0
338         MOV     D0Re0, D0.7
339         MOV     D1Re0, D1.7
340         SUBS    D1Ar5, D1Ar5, #1
341         BNE     $Lfaligned_4
342         ANDS    D1Ar3, D1Ar3, #7
343         BZ      $Lfbyte_loop_exit
344         ! Adjust A1.2
345         ADD     A1.2, A1.2, D0Ar4
346         B       $Lfbyte_loop
347
348         .size _memmove,.-_memmove
349
350 libc_hidden_def(memmove)