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