xref: /minix3/common/lib/libc/arch/arm/string/memmove.S (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1*0a6a1f1dSLionel Sambuc/*	$NetBSD: memmove.S,v 1.9 2015/03/26 13:34:51 justin Exp $	*/
2b6cbf720SGianluca Guida
3b6cbf720SGianluca Guida/*-
4b6cbf720SGianluca Guida * Copyright (c) 1997 The NetBSD Foundation, Inc.
5b6cbf720SGianluca Guida * All rights reserved.
6b6cbf720SGianluca Guida *
7b6cbf720SGianluca Guida * This code is derived from software contributed to The NetBSD Foundation
8b6cbf720SGianluca Guida * by Neil A. Carson and Mark Brinicombe
9b6cbf720SGianluca Guida *
10b6cbf720SGianluca Guida * Redistribution and use in source and binary forms, with or without
11b6cbf720SGianluca Guida * modification, are permitted provided that the following conditions
12b6cbf720SGianluca Guida * are met:
13b6cbf720SGianluca Guida * 1. Redistributions of source code must retain the above copyright
14b6cbf720SGianluca Guida *    notice, this list of conditions and the following disclaimer.
15b6cbf720SGianluca Guida * 2. Redistributions in binary form must reproduce the above copyright
16b6cbf720SGianluca Guida *    notice, this list of conditions and the following disclaimer in the
17b6cbf720SGianluca Guida *    documentation and/or other materials provided with the distribution.
18b6cbf720SGianluca Guida *
19b6cbf720SGianluca Guida * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20b6cbf720SGianluca Guida * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21b6cbf720SGianluca Guida * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22b6cbf720SGianluca Guida * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23b6cbf720SGianluca Guida * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24b6cbf720SGianluca Guida * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25b6cbf720SGianluca Guida * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26b6cbf720SGianluca Guida * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27b6cbf720SGianluca Guida * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28b6cbf720SGianluca Guida * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29b6cbf720SGianluca Guida * POSSIBILITY OF SUCH DAMAGE.
30b6cbf720SGianluca Guida */
31b6cbf720SGianluca Guida
32b6cbf720SGianluca Guida#include <machine/asm.h>
33b6cbf720SGianluca Guida
34b6cbf720SGianluca Guida#ifndef _BCOPY
35b6cbf720SGianluca Guida/* LINTSTUB: Func: void *memmove(void *, const void *, size_t) */
36b6cbf720SGianluca GuidaENTRY(memmove)
37b6cbf720SGianluca Guida#else
38b6cbf720SGianluca Guida/* bcopy = memcpy/memmove with arguments reversed. */
39b6cbf720SGianluca Guida/* LINTSTUB: Func: void bcopy(void *, void *, size_t) */
40b6cbf720SGianluca GuidaENTRY(bcopy)
41b6cbf720SGianluca Guida	/* switch the source and destination registers */
42b6cbf720SGianluca Guida	eor     r0, r1, r0
43b6cbf720SGianluca Guida	eor     r1, r0, r1
44b6cbf720SGianluca Guida	eor     r0, r1, r0
45b6cbf720SGianluca Guida#endif
46b6cbf720SGianluca Guida	/* Do the buffers overlap? */
47b6cbf720SGianluca Guida	cmp	r0, r1
48b6cbf720SGianluca Guida	RETc(eq)		/* Bail now if src/dst are the same */
49b6cbf720SGianluca Guida	subhs	r3, r0, r1	/* if (dst > src) r3 = dst - src */
50b6cbf720SGianluca Guida	sublo	r3, r1, r0	/* if (src > dst) r3 = src - dst */
51b6cbf720SGianluca Guida	cmp	r3, r2		/* if (r3 >= len) we have an overlap */
5284d9c625SLionel Sambuc	bhs	PLT_SYM(_C_LABEL(memcpy))
53b6cbf720SGianluca Guida
54b6cbf720SGianluca Guida	/* Determine copy direction */
55b6cbf720SGianluca Guida	cmp	r1, r0
56b6cbf720SGianluca Guida	bcc	.Lmemmove_backwards
57b6cbf720SGianluca Guida
58b6cbf720SGianluca Guida	moveq	r0, #0			/* Quick abort for len=0 */
59b6cbf720SGianluca Guida	RETc(eq)
60b6cbf720SGianluca Guida
6184d9c625SLionel Sambuc	push	{r0, lr}		/* memmove() returns dest addr */
62b6cbf720SGianluca Guida	subs	r2, r2, #4
63b6cbf720SGianluca Guida	blt	.Lmemmove_fl4		/* less than 4 bytes */
64b6cbf720SGianluca Guida	ands	r12, r0, #3
65b6cbf720SGianluca Guida	bne	.Lmemmove_fdestul	/* oh unaligned destination addr */
66b6cbf720SGianluca Guida	ands	r12, r1, #3
67b6cbf720SGianluca Guida	bne	.Lmemmove_fsrcul		/* oh unaligned source addr */
68b6cbf720SGianluca Guida
69b6cbf720SGianluca Guida.Lmemmove_ft8:
70b6cbf720SGianluca Guida	/* We have aligned source and destination */
71b6cbf720SGianluca Guida	subs	r2, r2, #8
72b6cbf720SGianluca Guida	blt	.Lmemmove_fl12		/* less than 12 bytes (4 from above) */
73b6cbf720SGianluca Guida	subs	r2, r2, #0x14
74b6cbf720SGianluca Guida	blt	.Lmemmove_fl32		/* less than 32 bytes (12 from above) */
7584d9c625SLionel Sambuc	push	{r4}		/* borrow r4 */
76b6cbf720SGianluca Guida
77b6cbf720SGianluca Guida	/* blat 32 bytes at a time */
78b6cbf720SGianluca Guida	/* XXX for really big copies perhaps we should use more registers */
79b6cbf720SGianluca Guida.Lmemmove_floop32:
80b6cbf720SGianluca Guida	ldmia	r1!, {r3, r4, r12, lr}
81b6cbf720SGianluca Guida	stmia	r0!, {r3, r4, r12, lr}
82b6cbf720SGianluca Guida	ldmia	r1!, {r3, r4, r12, lr}
83b6cbf720SGianluca Guida	stmia	r0!, {r3, r4, r12, lr}
84b6cbf720SGianluca Guida	subs	r2, r2, #0x20
85b6cbf720SGianluca Guida	bge	.Lmemmove_floop32
86b6cbf720SGianluca Guida
87b6cbf720SGianluca Guida	cmn	r2, #0x10
8884d9c625SLionel Sambuc	ldmiage	r1!, {r3, r4, r12, lr}	/* blat a remaining 16 bytes */
8984d9c625SLionel Sambuc	stmiage	r0!, {r3, r4, r12, lr}
90b6cbf720SGianluca Guida	subge	r2, r2, #0x10
9184d9c625SLionel Sambuc	pop	{r4}		/* return r4 */
92b6cbf720SGianluca Guida
93b6cbf720SGianluca Guida.Lmemmove_fl32:
94b6cbf720SGianluca Guida	adds	r2, r2, #0x14
95b6cbf720SGianluca Guida
96b6cbf720SGianluca Guida	/* blat 12 bytes at a time */
97b6cbf720SGianluca Guida.Lmemmove_floop12:
9884d9c625SLionel Sambuc	ldmiage	r1!, {r3, r12, lr}
9984d9c625SLionel Sambuc	stmiage	r0!, {r3, r12, lr}
10084d9c625SLionel Sambuc	subsge	r2, r2, #0x0c
101b6cbf720SGianluca Guida	bge	.Lmemmove_floop12
102b6cbf720SGianluca Guida
103b6cbf720SGianluca Guida.Lmemmove_fl12:
104b6cbf720SGianluca Guida	adds	r2, r2, #8
105b6cbf720SGianluca Guida	blt	.Lmemmove_fl4
106b6cbf720SGianluca Guida
107b6cbf720SGianluca Guida	subs	r2, r2, #4
108b6cbf720SGianluca Guida	ldrlt	r3, [r1], #4
109b6cbf720SGianluca Guida	strlt	r3, [r0], #4
11084d9c625SLionel Sambuc	ldmiage	r1!, {r3, r12}
11184d9c625SLionel Sambuc	stmiage	r0!, {r3, r12}
112b6cbf720SGianluca Guida	subge	r2, r2, #4
113b6cbf720SGianluca Guida
114b6cbf720SGianluca Guida.Lmemmove_fl4:
115b6cbf720SGianluca Guida	/* less than 4 bytes to go */
116b6cbf720SGianluca Guida	adds	r2, r2, #4
11784d9c625SLionel Sambuc	popeq	{r0, pc}		/* done */
118b6cbf720SGianluca Guida
119b6cbf720SGianluca Guida	/* copy the crud byte at a time */
120b6cbf720SGianluca Guida	cmp	r2, #2
121b6cbf720SGianluca Guida	ldrb	r3, [r1], #1
122b6cbf720SGianluca Guida	strb	r3, [r0], #1
12384d9c625SLionel Sambuc	ldrbge	r3, [r1], #1
12484d9c625SLionel Sambuc	strbge	r3, [r0], #1
12584d9c625SLionel Sambuc	ldrbgt	r3, [r1], #1
12684d9c625SLionel Sambuc	strbgt	r3, [r0], #1
12784d9c625SLionel Sambuc	pop	{r0, pc}
128b6cbf720SGianluca Guida
129b6cbf720SGianluca Guida	/* erg - unaligned destination */
130b6cbf720SGianluca Guida.Lmemmove_fdestul:
131b6cbf720SGianluca Guida	rsb	r12, r12, #4
132b6cbf720SGianluca Guida	cmp	r12, #2
133b6cbf720SGianluca Guida
134b6cbf720SGianluca Guida	/* align destination with byte copies */
135b6cbf720SGianluca Guida	ldrb	r3, [r1], #1
136b6cbf720SGianluca Guida	strb	r3, [r0], #1
13784d9c625SLionel Sambuc	ldrbge	r3, [r1], #1
13884d9c625SLionel Sambuc	strbge	r3, [r0], #1
13984d9c625SLionel Sambuc	ldrbgt	r3, [r1], #1
14084d9c625SLionel Sambuc	strbgt	r3, [r0], #1
141b6cbf720SGianluca Guida	subs	r2, r2, r12
142b6cbf720SGianluca Guida	blt	.Lmemmove_fl4		/* less the 4 bytes */
143b6cbf720SGianluca Guida
144b6cbf720SGianluca Guida	ands	r12, r1, #3
145b6cbf720SGianluca Guida	beq	.Lmemmove_ft8		/* we have an aligned source */
146b6cbf720SGianluca Guida
147b6cbf720SGianluca Guida	/* erg - unaligned source */
148b6cbf720SGianluca Guida	/* This is where it gets nasty ... */
149b6cbf720SGianluca Guida.Lmemmove_fsrcul:
150b6cbf720SGianluca Guida	bic	r1, r1, #3
151b6cbf720SGianluca Guida	ldr	lr, [r1], #4
152b6cbf720SGianluca Guida	cmp	r12, #2
153b6cbf720SGianluca Guida	bgt	.Lmemmove_fsrcul3
154b6cbf720SGianluca Guida	beq	.Lmemmove_fsrcul2
155b6cbf720SGianluca Guida	cmp	r2, #0x0c
156b6cbf720SGianluca Guida	blt	.Lmemmove_fsrcul1loop4
157b6cbf720SGianluca Guida	sub	r2, r2, #0x0c
15884d9c625SLionel Sambuc	push	{r4, r5}
159b6cbf720SGianluca Guida
160b6cbf720SGianluca Guida.Lmemmove_fsrcul1loop16:
161b6cbf720SGianluca Guida#ifdef __ARMEB__
162b6cbf720SGianluca Guida	mov	r3, lr, lsl #8
163b6cbf720SGianluca Guida#else
164b6cbf720SGianluca Guida	mov	r3, lr, lsr #8
165b6cbf720SGianluca Guida#endif
166b6cbf720SGianluca Guida	ldmia	r1!, {r4, r5, r12, lr}
167b6cbf720SGianluca Guida#ifdef __ARMEB__
168b6cbf720SGianluca Guida	orr	r3, r3, r4, lsr #24
169b6cbf720SGianluca Guida	mov	r4, r4, lsl #8
170b6cbf720SGianluca Guida	orr	r4, r4, r5, lsr #24
171b6cbf720SGianluca Guida	mov	r5, r5, lsl #8
172b6cbf720SGianluca Guida	orr	r5, r5, r12, lsr #24
173b6cbf720SGianluca Guida	mov	r12, r12, lsl #8
174b6cbf720SGianluca Guida	orr	r12, r12, lr, lsr #24
175b6cbf720SGianluca Guida#else
176b6cbf720SGianluca Guida	orr	r3, r3, r4, lsl #24
177b6cbf720SGianluca Guida	mov	r4, r4, lsr #8
178b6cbf720SGianluca Guida	orr	r4, r4, r5, lsl #24
179b6cbf720SGianluca Guida	mov	r5, r5, lsr #8
180b6cbf720SGianluca Guida	orr	r5, r5, r12, lsl #24
181b6cbf720SGianluca Guida	mov	r12, r12, lsr #8
182b6cbf720SGianluca Guida	orr	r12, r12, lr, lsl #24
183b6cbf720SGianluca Guida#endif
184b6cbf720SGianluca Guida	stmia	r0!, {r3-r5, r12}
185b6cbf720SGianluca Guida	subs	r2, r2, #0x10
186b6cbf720SGianluca Guida	bge	.Lmemmove_fsrcul1loop16
18784d9c625SLionel Sambuc	pop	{r4, r5}
188b6cbf720SGianluca Guida	adds	r2, r2, #0x0c
189b6cbf720SGianluca Guida	blt	.Lmemmove_fsrcul1l4
190b6cbf720SGianluca Guida
191b6cbf720SGianluca Guida.Lmemmove_fsrcul1loop4:
192b6cbf720SGianluca Guida#ifdef __ARMEB__
193b6cbf720SGianluca Guida	mov	r12, lr, lsl #8
194b6cbf720SGianluca Guida#else
195b6cbf720SGianluca Guida	mov	r12, lr, lsr #8
196b6cbf720SGianluca Guida#endif
197b6cbf720SGianluca Guida	ldr	lr, [r1], #4
198b6cbf720SGianluca Guida#ifdef __ARMEB__
199b6cbf720SGianluca Guida	orr	r12, r12, lr, lsr #24
200b6cbf720SGianluca Guida#else
201b6cbf720SGianluca Guida	orr	r12, r12, lr, lsl #24
202b6cbf720SGianluca Guida#endif
203b6cbf720SGianluca Guida	str	r12, [r0], #4
204b6cbf720SGianluca Guida	subs	r2, r2, #4
205b6cbf720SGianluca Guida	bge	.Lmemmove_fsrcul1loop4
206b6cbf720SGianluca Guida
207b6cbf720SGianluca Guida.Lmemmove_fsrcul1l4:
208b6cbf720SGianluca Guida	sub	r1, r1, #3
209b6cbf720SGianluca Guida	b	.Lmemmove_fl4
210b6cbf720SGianluca Guida
211b6cbf720SGianluca Guida.Lmemmove_fsrcul2:
212b6cbf720SGianluca Guida	cmp	r2, #0x0c
213b6cbf720SGianluca Guida	blt	.Lmemmove_fsrcul2loop4
214b6cbf720SGianluca Guida	sub	r2, r2, #0x0c
21584d9c625SLionel Sambuc	push	{r4, r5}
216b6cbf720SGianluca Guida
217b6cbf720SGianluca Guida.Lmemmove_fsrcul2loop16:
218b6cbf720SGianluca Guida#ifdef __ARMEB__
219b6cbf720SGianluca Guida	mov	r3, lr, lsl #16
220b6cbf720SGianluca Guida#else
221b6cbf720SGianluca Guida	mov	r3, lr, lsr #16
222b6cbf720SGianluca Guida#endif
223b6cbf720SGianluca Guida	ldmia	r1!, {r4, r5, r12, lr}
224b6cbf720SGianluca Guida#ifdef __ARMEB__
225b6cbf720SGianluca Guida	orr	r3, r3, r4, lsr #16
226b6cbf720SGianluca Guida	mov	r4, r4, lsl #16
227b6cbf720SGianluca Guida	orr	r4, r4, r5, lsr #16
228b6cbf720SGianluca Guida	mov	r5, r5, lsl #16
229b6cbf720SGianluca Guida	orr	r5, r5, r12, lsr #16
230b6cbf720SGianluca Guida	mov	r12, r12, lsl #16
231b6cbf720SGianluca Guida	orr	r12, r12, lr, lsr #16
232b6cbf720SGianluca Guida#else
233b6cbf720SGianluca Guida	orr	r3, r3, r4, lsl #16
234b6cbf720SGianluca Guida	mov	r4, r4, lsr #16
235b6cbf720SGianluca Guida	orr	r4, r4, r5, lsl #16
236b6cbf720SGianluca Guida	mov	r5, r5, lsr #16
237b6cbf720SGianluca Guida	orr	r5, r5, r12, lsl #16
238b6cbf720SGianluca Guida	mov	r12, r12, lsr #16
239b6cbf720SGianluca Guida	orr	r12, r12, lr, lsl #16
240b6cbf720SGianluca Guida#endif
241b6cbf720SGianluca Guida	stmia	r0!, {r3-r5, r12}
242b6cbf720SGianluca Guida	subs	r2, r2, #0x10
243b6cbf720SGianluca Guida	bge	.Lmemmove_fsrcul2loop16
24484d9c625SLionel Sambuc	pop	{r4, r5}
245b6cbf720SGianluca Guida	adds	r2, r2, #0x0c
246b6cbf720SGianluca Guida	blt	.Lmemmove_fsrcul2l4
247b6cbf720SGianluca Guida
248b6cbf720SGianluca Guida.Lmemmove_fsrcul2loop4:
249b6cbf720SGianluca Guida#ifdef __ARMEB__
250b6cbf720SGianluca Guida	mov	r12, lr, lsl #16
251b6cbf720SGianluca Guida#else
252b6cbf720SGianluca Guida	mov	r12, lr, lsr #16
253b6cbf720SGianluca Guida#endif
254b6cbf720SGianluca Guida	ldr	lr, [r1], #4
255b6cbf720SGianluca Guida#ifdef __ARMEB__
256b6cbf720SGianluca Guida	orr	r12, r12, lr, lsr #16
257b6cbf720SGianluca Guida#else
258b6cbf720SGianluca Guida	orr	r12, r12, lr, lsl #16
259b6cbf720SGianluca Guida#endif
260b6cbf720SGianluca Guida	str	r12, [r0], #4
261b6cbf720SGianluca Guida	subs	r2, r2, #4
262b6cbf720SGianluca Guida	bge	.Lmemmove_fsrcul2loop4
263b6cbf720SGianluca Guida
264b6cbf720SGianluca Guida.Lmemmove_fsrcul2l4:
265b6cbf720SGianluca Guida	sub	r1, r1, #2
266b6cbf720SGianluca Guida	b	.Lmemmove_fl4
267b6cbf720SGianluca Guida
268b6cbf720SGianluca Guida.Lmemmove_fsrcul3:
269b6cbf720SGianluca Guida	cmp	r2, #0x0c
270b6cbf720SGianluca Guida	blt	.Lmemmove_fsrcul3loop4
271b6cbf720SGianluca Guida	sub	r2, r2, #0x0c
27284d9c625SLionel Sambuc	push	{r4, r5}
273b6cbf720SGianluca Guida
274b6cbf720SGianluca Guida.Lmemmove_fsrcul3loop16:
275b6cbf720SGianluca Guida#ifdef __ARMEB__
276b6cbf720SGianluca Guida	mov	r3, lr, lsl #24
277b6cbf720SGianluca Guida#else
278b6cbf720SGianluca Guida	mov	r3, lr, lsr #24
279b6cbf720SGianluca Guida#endif
280b6cbf720SGianluca Guida	ldmia	r1!, {r4, r5, r12, lr}
281b6cbf720SGianluca Guida#ifdef __ARMEB__
282b6cbf720SGianluca Guida	orr	r3, r3, r4, lsr #8
283b6cbf720SGianluca Guida	mov	r4, r4, lsl #24
284b6cbf720SGianluca Guida	orr	r4, r4, r5, lsr #8
285b6cbf720SGianluca Guida	mov	r5, r5, lsl #24
286b6cbf720SGianluca Guida	orr	r5, r5, r12, lsr #8
287b6cbf720SGianluca Guida	mov	r12, r12, lsl #24
288b6cbf720SGianluca Guida	orr	r12, r12, lr, lsr #8
289b6cbf720SGianluca Guida#else
290b6cbf720SGianluca Guida	orr	r3, r3, r4, lsl #8
291b6cbf720SGianluca Guida	mov	r4, r4, lsr #24
292b6cbf720SGianluca Guida	orr	r4, r4, r5, lsl #8
293b6cbf720SGianluca Guida	mov	r5, r5, lsr #24
294b6cbf720SGianluca Guida	orr	r5, r5, r12, lsl #8
295b6cbf720SGianluca Guida	mov	r12, r12, lsr #24
296b6cbf720SGianluca Guida	orr	r12, r12, lr, lsl #8
297b6cbf720SGianluca Guida#endif
298b6cbf720SGianluca Guida	stmia	r0!, {r3-r5, r12}
299b6cbf720SGianluca Guida	subs	r2, r2, #0x10
300b6cbf720SGianluca Guida	bge	.Lmemmove_fsrcul3loop16
30184d9c625SLionel Sambuc	pop	{r4, r5}
302b6cbf720SGianluca Guida	adds	r2, r2, #0x0c
303b6cbf720SGianluca Guida	blt	.Lmemmove_fsrcul3l4
304b6cbf720SGianluca Guida
305b6cbf720SGianluca Guida.Lmemmove_fsrcul3loop4:
306b6cbf720SGianluca Guida#ifdef __ARMEB__
307b6cbf720SGianluca Guida	mov	r12, lr, lsl #24
308b6cbf720SGianluca Guida#else
309b6cbf720SGianluca Guida	mov	r12, lr, lsr #24
310b6cbf720SGianluca Guida#endif
311b6cbf720SGianluca Guida	ldr	lr, [r1], #4
312b6cbf720SGianluca Guida#ifdef __ARMEB__
313b6cbf720SGianluca Guida	orr	r12, r12, lr, lsr #8
314b6cbf720SGianluca Guida#else
315b6cbf720SGianluca Guida	orr	r12, r12, lr, lsl #8
316b6cbf720SGianluca Guida#endif
317b6cbf720SGianluca Guida	str	r12, [r0], #4
318b6cbf720SGianluca Guida	subs	r2, r2, #4
319b6cbf720SGianluca Guida	bge	.Lmemmove_fsrcul3loop4
320b6cbf720SGianluca Guida
321b6cbf720SGianluca Guida.Lmemmove_fsrcul3l4:
322b6cbf720SGianluca Guida	sub	r1, r1, #1
323b6cbf720SGianluca Guida	b	.Lmemmove_fl4
324b6cbf720SGianluca Guida
325b6cbf720SGianluca Guida.Lmemmove_backwards:
326b6cbf720SGianluca Guida	add	r1, r1, r2
327b6cbf720SGianluca Guida	add	r0, r0, r2
328b6cbf720SGianluca Guida	subs	r2, r2, #4
329b6cbf720SGianluca Guida	blt	.Lmemmove_bl4		/* less than 4 bytes */
330b6cbf720SGianluca Guida	ands	r12, r0, #3
331b6cbf720SGianluca Guida	bne	.Lmemmove_bdestul	/* oh unaligned destination addr */
332b6cbf720SGianluca Guida	ands	r12, r1, #3
333b6cbf720SGianluca Guida	bne	.Lmemmove_bsrcul		/* oh unaligned source addr */
334b6cbf720SGianluca Guida
335b6cbf720SGianluca Guida.Lmemmove_bt8:
336b6cbf720SGianluca Guida	/* We have aligned source and destination */
337b6cbf720SGianluca Guida	subs	r2, r2, #8
338b6cbf720SGianluca Guida	blt	.Lmemmove_bl12		/* less than 12 bytes (4 from above) */
33984d9c625SLionel Sambuc	push	{r4, lr}
340b6cbf720SGianluca Guida	subs	r2, r2, #0x14		/* less than 32 bytes (12 from above) */
341b6cbf720SGianluca Guida	blt	.Lmemmove_bl32
342b6cbf720SGianluca Guida
343b6cbf720SGianluca Guida	/* blat 32 bytes at a time */
344b6cbf720SGianluca Guida	/* XXX for really big copies perhaps we should use more registers */
345b6cbf720SGianluca Guida.Lmemmove_bloop32:
346b6cbf720SGianluca Guida	ldmdb	r1!, {r3, r4, r12, lr}
347b6cbf720SGianluca Guida	stmdb	r0!, {r3, r4, r12, lr}
348b6cbf720SGianluca Guida	ldmdb	r1!, {r3, r4, r12, lr}
349b6cbf720SGianluca Guida	stmdb	r0!, {r3, r4, r12, lr}
350b6cbf720SGianluca Guida	subs	r2, r2, #0x20
351b6cbf720SGianluca Guida	bge	.Lmemmove_bloop32
352b6cbf720SGianluca Guida
353b6cbf720SGianluca Guida.Lmemmove_bl32:
354b6cbf720SGianluca Guida	cmn	r2, #0x10
35584d9c625SLionel Sambuc	ldmdbge	r1!, {r3, r4, r12, lr}	/* blat a remaining 16 bytes */
35684d9c625SLionel Sambuc	stmdbge	r0!, {r3, r4, r12, lr}
357b6cbf720SGianluca Guida	subge	r2, r2, #0x10
358b6cbf720SGianluca Guida	adds	r2, r2, #0x14
35984d9c625SLionel Sambuc	ldmdbge	r1!, {r3, r12, lr}	/* blat a remaining 12 bytes */
36084d9c625SLionel Sambuc	stmdbge	r0!, {r3, r12, lr}
361b6cbf720SGianluca Guida	subge	r2, r2, #0x0c
36284d9c625SLionel Sambuc	pop	{r4, lr}
363b6cbf720SGianluca Guida
364b6cbf720SGianluca Guida.Lmemmove_bl12:
365b6cbf720SGianluca Guida	adds	r2, r2, #8
366b6cbf720SGianluca Guida	blt	.Lmemmove_bl4
367b6cbf720SGianluca Guida	subs	r2, r2, #4
368b6cbf720SGianluca Guida	ldrlt	r3, [r1, #-4]!
369b6cbf720SGianluca Guida	strlt	r3, [r0, #-4]!
37084d9c625SLionel Sambuc	ldmdbge	r1!, {r3, r12}
37184d9c625SLionel Sambuc	stmdbge	r0!, {r3, r12}
372b6cbf720SGianluca Guida	subge	r2, r2, #4
373b6cbf720SGianluca Guida
374b6cbf720SGianluca Guida.Lmemmove_bl4:
375b6cbf720SGianluca Guida	/* less than 4 bytes to go */
376b6cbf720SGianluca Guida	adds	r2, r2, #4
377b6cbf720SGianluca Guida	RETc(eq)
378b6cbf720SGianluca Guida
379b6cbf720SGianluca Guida	/* copy the crud byte at a time */
380b6cbf720SGianluca Guida	cmp	r2, #2
381b6cbf720SGianluca Guida	ldrb	r3, [r1, #-1]!
382b6cbf720SGianluca Guida	strb	r3, [r0, #-1]!
38384d9c625SLionel Sambuc	ldrbge	r3, [r1, #-1]!
38484d9c625SLionel Sambuc	strbge	r3, [r0, #-1]!
38584d9c625SLionel Sambuc	ldrbgt	r3, [r1, #-1]!
38684d9c625SLionel Sambuc	strbgt	r3, [r0, #-1]!
387b6cbf720SGianluca Guida	RET
388b6cbf720SGianluca Guida
389b6cbf720SGianluca Guida	/* erg - unaligned destination */
390b6cbf720SGianluca Guida.Lmemmove_bdestul:
391b6cbf720SGianluca Guida	cmp	r12, #2
392b6cbf720SGianluca Guida
393b6cbf720SGianluca Guida	/* align destination with byte copies */
394b6cbf720SGianluca Guida	ldrb	r3, [r1, #-1]!
395b6cbf720SGianluca Guida	strb	r3, [r0, #-1]!
39684d9c625SLionel Sambuc	ldrbge	r3, [r1, #-1]!
39784d9c625SLionel Sambuc	strbge	r3, [r0, #-1]!
39884d9c625SLionel Sambuc	ldrbgt	r3, [r1, #-1]!
39984d9c625SLionel Sambuc	strbgt	r3, [r0, #-1]!
400b6cbf720SGianluca Guida	subs	r2, r2, r12
401b6cbf720SGianluca Guida	blt	.Lmemmove_bl4		/* less than 4 bytes to go */
402b6cbf720SGianluca Guida	ands	r12, r1, #3
403b6cbf720SGianluca Guida	beq	.Lmemmove_bt8		/* we have an aligned source */
404b6cbf720SGianluca Guida
405b6cbf720SGianluca Guida	/* erg - unaligned source */
406b6cbf720SGianluca Guida	/* This is where it gets nasty ... */
407b6cbf720SGianluca Guida.Lmemmove_bsrcul:
408b6cbf720SGianluca Guida	bic	r1, r1, #3
409b6cbf720SGianluca Guida	ldr	r3, [r1, #0]
410b6cbf720SGianluca Guida	cmp	r12, #2
411b6cbf720SGianluca Guida	blt	.Lmemmove_bsrcul1
412b6cbf720SGianluca Guida	beq	.Lmemmove_bsrcul2
413b6cbf720SGianluca Guida	cmp	r2, #0x0c
414b6cbf720SGianluca Guida	blt	.Lmemmove_bsrcul3loop4
415b6cbf720SGianluca Guida	sub	r2, r2, #0x0c
41684d9c625SLionel Sambuc	push	{r4, r5, lr}
417b6cbf720SGianluca Guida
418b6cbf720SGianluca Guida.Lmemmove_bsrcul3loop16:
419b6cbf720SGianluca Guida#ifdef __ARMEB__
420b6cbf720SGianluca Guida	mov	lr, r3, lsr #8
421b6cbf720SGianluca Guida#else
422b6cbf720SGianluca Guida	mov	lr, r3, lsl #8
423b6cbf720SGianluca Guida#endif
424b6cbf720SGianluca Guida	ldmdb	r1!, {r3-r5, r12}
425b6cbf720SGianluca Guida#ifdef __ARMEB__
426b6cbf720SGianluca Guida	orr	lr, lr, r12, lsl #24
427b6cbf720SGianluca Guida	mov	r12, r12, lsr #8
428b6cbf720SGianluca Guida	orr	r12, r12, r5, lsl #24
429b6cbf720SGianluca Guida	mov	r5, r5, lsr #8
430b6cbf720SGianluca Guida	orr	r5, r5, r4, lsl #24
431b6cbf720SGianluca Guida	mov	r4, r4, lsr #8
432b6cbf720SGianluca Guida	orr	r4, r4, r3, lsl #24
433b6cbf720SGianluca Guida#else
434b6cbf720SGianluca Guida	orr	lr, lr, r12, lsr #24
435b6cbf720SGianluca Guida	mov	r12, r12, lsl #8
436b6cbf720SGianluca Guida	orr	r12, r12, r5, lsr #24
437b6cbf720SGianluca Guida	mov	r5, r5, lsl #8
438b6cbf720SGianluca Guida	orr	r5, r5, r4, lsr #24
439b6cbf720SGianluca Guida	mov	r4, r4, lsl #8
440b6cbf720SGianluca Guida	orr	r4, r4, r3, lsr #24
441b6cbf720SGianluca Guida#endif
442b6cbf720SGianluca Guida	stmdb	r0!, {r4, r5, r12, lr}
443b6cbf720SGianluca Guida	subs	r2, r2, #0x10
444b6cbf720SGianluca Guida	bge	.Lmemmove_bsrcul3loop16
44584d9c625SLionel Sambuc	pop	{r4, r5, lr}
446b6cbf720SGianluca Guida	adds	r2, r2, #0x0c
447b6cbf720SGianluca Guida	blt	.Lmemmove_bsrcul3l4
448b6cbf720SGianluca Guida
449b6cbf720SGianluca Guida.Lmemmove_bsrcul3loop4:
450b6cbf720SGianluca Guida#ifdef __ARMEB__
451b6cbf720SGianluca Guida	mov	r12, r3, lsr #8
452b6cbf720SGianluca Guida#else
453b6cbf720SGianluca Guida	mov	r12, r3, lsl #8
454b6cbf720SGianluca Guida#endif
455b6cbf720SGianluca Guida	ldr	r3, [r1, #-4]!
456b6cbf720SGianluca Guida#ifdef __ARMEB__
457b6cbf720SGianluca Guida	orr	r12, r12, r3, lsl #24
458b6cbf720SGianluca Guida#else
459b6cbf720SGianluca Guida	orr	r12, r12, r3, lsr #24
460b6cbf720SGianluca Guida#endif
461b6cbf720SGianluca Guida	str	r12, [r0, #-4]!
462b6cbf720SGianluca Guida	subs	r2, r2, #4
463b6cbf720SGianluca Guida	bge	.Lmemmove_bsrcul3loop4
464b6cbf720SGianluca Guida
465b6cbf720SGianluca Guida.Lmemmove_bsrcul3l4:
466b6cbf720SGianluca Guida	add	r1, r1, #3
467b6cbf720SGianluca Guida	b	.Lmemmove_bl4
468b6cbf720SGianluca Guida
469b6cbf720SGianluca Guida.Lmemmove_bsrcul2:
470b6cbf720SGianluca Guida	cmp	r2, #0x0c
471b6cbf720SGianluca Guida	blt	.Lmemmove_bsrcul2loop4
472b6cbf720SGianluca Guida	sub	r2, r2, #0x0c
47384d9c625SLionel Sambuc	push	{r4, r5, lr}
474b6cbf720SGianluca Guida
475b6cbf720SGianluca Guida.Lmemmove_bsrcul2loop16:
476b6cbf720SGianluca Guida#ifdef __ARMEB__
477b6cbf720SGianluca Guida	mov	lr, r3, lsr #16
478b6cbf720SGianluca Guida#else
479b6cbf720SGianluca Guida	mov	lr, r3, lsl #16
480b6cbf720SGianluca Guida#endif
481b6cbf720SGianluca Guida	ldmdb	r1!, {r3-r5, r12}
482b6cbf720SGianluca Guida#ifdef __ARMEB__
483b6cbf720SGianluca Guida	orr	lr, lr, r12, lsl #16
484b6cbf720SGianluca Guida	mov	r12, r12, lsr #16
485b6cbf720SGianluca Guida	orr	r12, r12, r5, lsl #16
486b6cbf720SGianluca Guida	mov	r5, r5, lsr #16
487b6cbf720SGianluca Guida	orr	r5, r5, r4, lsl #16
488b6cbf720SGianluca Guida	mov	r4, r4, lsr #16
489b6cbf720SGianluca Guida	orr	r4, r4, r3, lsl #16
490b6cbf720SGianluca Guida#else
491b6cbf720SGianluca Guida	orr	lr, lr, r12, lsr #16
492b6cbf720SGianluca Guida	mov	r12, r12, lsl #16
493b6cbf720SGianluca Guida	orr	r12, r12, r5, lsr #16
494b6cbf720SGianluca Guida	mov	r5, r5, lsl #16
495b6cbf720SGianluca Guida	orr	r5, r5, r4, lsr #16
496b6cbf720SGianluca Guida	mov	r4, r4, lsl #16
497b6cbf720SGianluca Guida	orr	r4, r4, r3, lsr #16
498b6cbf720SGianluca Guida#endif
499b6cbf720SGianluca Guida	stmdb	r0!, {r4, r5, r12, lr}
500b6cbf720SGianluca Guida	subs	r2, r2, #0x10
501b6cbf720SGianluca Guida	bge	.Lmemmove_bsrcul2loop16
50284d9c625SLionel Sambuc	pop	{r4, r5, lr}
503b6cbf720SGianluca Guida	adds	r2, r2, #0x0c
504b6cbf720SGianluca Guida	blt	.Lmemmove_bsrcul2l4
505b6cbf720SGianluca Guida
506b6cbf720SGianluca Guida.Lmemmove_bsrcul2loop4:
507b6cbf720SGianluca Guida#ifdef __ARMEB__
508b6cbf720SGianluca Guida	mov	r12, r3, lsr #16
509b6cbf720SGianluca Guida#else
510b6cbf720SGianluca Guida	mov	r12, r3, lsl #16
511b6cbf720SGianluca Guida#endif
512b6cbf720SGianluca Guida	ldr	r3, [r1, #-4]!
513b6cbf720SGianluca Guida#ifdef __ARMEB__
514b6cbf720SGianluca Guida	orr	r12, r12, r3, lsl #16
515b6cbf720SGianluca Guida#else
516b6cbf720SGianluca Guida	orr	r12, r12, r3, lsr #16
517b6cbf720SGianluca Guida#endif
518b6cbf720SGianluca Guida	str	r12, [r0, #-4]!
519b6cbf720SGianluca Guida	subs	r2, r2, #4
520b6cbf720SGianluca Guida	bge	.Lmemmove_bsrcul2loop4
521b6cbf720SGianluca Guida
522b6cbf720SGianluca Guida.Lmemmove_bsrcul2l4:
523b6cbf720SGianluca Guida	add	r1, r1, #2
524b6cbf720SGianluca Guida	b	.Lmemmove_bl4
525b6cbf720SGianluca Guida
526b6cbf720SGianluca Guida.Lmemmove_bsrcul1:
527b6cbf720SGianluca Guida	cmp	r2, #0x0c
528b6cbf720SGianluca Guida	blt	.Lmemmove_bsrcul1loop4
529b6cbf720SGianluca Guida	sub	r2, r2, #0x0c
53084d9c625SLionel Sambuc	push	{r4, r5, lr}
531b6cbf720SGianluca Guida
532b6cbf720SGianluca Guida.Lmemmove_bsrcul1loop32:
533b6cbf720SGianluca Guida#ifdef __ARMEB__
534b6cbf720SGianluca Guida	mov	lr, r3, lsr #24
535b6cbf720SGianluca Guida#else
536b6cbf720SGianluca Guida	mov	lr, r3, lsl #24
537b6cbf720SGianluca Guida#endif
538b6cbf720SGianluca Guida	ldmdb	r1!, {r3-r5, r12}
539b6cbf720SGianluca Guida#ifdef __ARMEB__
540b6cbf720SGianluca Guida	orr	lr, lr, r12, lsl #8
541b6cbf720SGianluca Guida	mov	r12, r12, lsr #24
542b6cbf720SGianluca Guida	orr	r12, r12, r5, lsl #8
543b6cbf720SGianluca Guida	mov	r5, r5, lsr #24
544b6cbf720SGianluca Guida	orr	r5, r5, r4, lsl #8
545b6cbf720SGianluca Guida	mov	r4, r4, lsr #24
546b6cbf720SGianluca Guida	orr	r4, r4, r3, lsl #8
547b6cbf720SGianluca Guida#else
548b6cbf720SGianluca Guida	orr	lr, lr, r12, lsr #8
549b6cbf720SGianluca Guida	mov	r12, r12, lsl #24
550b6cbf720SGianluca Guida	orr	r12, r12, r5, lsr #8
551b6cbf720SGianluca Guida	mov	r5, r5, lsl #24
552b6cbf720SGianluca Guida	orr	r5, r5, r4, lsr #8
553b6cbf720SGianluca Guida	mov	r4, r4, lsl #24
554b6cbf720SGianluca Guida	orr	r4, r4, r3, lsr #8
555b6cbf720SGianluca Guida#endif
556b6cbf720SGianluca Guida	stmdb	r0!, {r4, r5, r12, lr}
557b6cbf720SGianluca Guida	subs	r2, r2, #0x10
558b6cbf720SGianluca Guida	bge	.Lmemmove_bsrcul1loop32
55984d9c625SLionel Sambuc	pop	{r4, r5, lr}
560b6cbf720SGianluca Guida	adds	r2, r2, #0x0c
561b6cbf720SGianluca Guida	blt	.Lmemmove_bsrcul1l4
562b6cbf720SGianluca Guida
563b6cbf720SGianluca Guida.Lmemmove_bsrcul1loop4:
564b6cbf720SGianluca Guida#ifdef __ARMEB__
565b6cbf720SGianluca Guida	mov	r12, r3, lsr #24
566b6cbf720SGianluca Guida#else
567b6cbf720SGianluca Guida	mov	r12, r3, lsl #24
568b6cbf720SGianluca Guida#endif
569b6cbf720SGianluca Guida	ldr	r3, [r1, #-4]!
570b6cbf720SGianluca Guida#ifdef __ARMEB__
571b6cbf720SGianluca Guida	orr	r12, r12, r3, lsl #8
572b6cbf720SGianluca Guida#else
573b6cbf720SGianluca Guida	orr	r12, r12, r3, lsr #8
574b6cbf720SGianluca Guida#endif
575b6cbf720SGianluca Guida	str	r12, [r0, #-4]!
576b6cbf720SGianluca Guida	subs	r2, r2, #4
577b6cbf720SGianluca Guida	bge	.Lmemmove_bsrcul1loop4
578b6cbf720SGianluca Guida
579b6cbf720SGianluca Guida.Lmemmove_bsrcul1l4:
580b6cbf720SGianluca Guida	add	r1, r1, #1
581b6cbf720SGianluca Guida	b	.Lmemmove_bl4
58284d9c625SLionel Sambuc#ifndef _BCOPY
58384d9c625SLionel SambucEND(memmove)
58484d9c625SLionel Sambuc#else
58584d9c625SLionel SambucEND(bcopy)
58684d9c625SLionel Sambuc#endif
58784d9c625SLionel Sambuc
588*0a6a1f1dSLionel Sambuc#if defined(__ARM_EABI__) && !defined(BCOPY) && !defined(_RUMPKERNEL)
58984d9c625SLionel SambucSTRONG_ALIAS(__aeabi_memmove, memmove)
590*0a6a1f1dSLionel SambucSTRONG_ALIAS(__aeabi_memmove4, memmove)
591*0a6a1f1dSLionel SambucSTRONG_ALIAS(__aeabi_memmove8, memmove)
59284d9c625SLionel Sambuc#endif
593