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
346