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