1129202Scognet/*	$NetBSD: memmove.S,v 1.4 2003/10/14 07:51:45 scw Exp $	*/
2129202Scognet
3129202Scognet/*-
4129202Scognet * Copyright (c) 1997 The NetBSD Foundation, Inc.
5129202Scognet * All rights reserved.
6129202Scognet *
7129202Scognet * This code is derived from software contributed to The NetBSD Foundation
8129202Scognet * by Neil A. Carson and Mark Brinicombe
9129202Scognet *
10129202Scognet * Redistribution and use in source and binary forms, with or without
11129202Scognet * modification, are permitted provided that the following conditions
12129202Scognet * are met:
13129202Scognet * 1. Redistributions of source code must retain the above copyright
14129202Scognet *    notice, this list of conditions and the following disclaimer.
15129202Scognet * 2. Redistributions in binary form must reproduce the above copyright
16129202Scognet *    notice, this list of conditions and the following disclaimer in the
17129202Scognet *    documentation and/or other materials provided with the distribution.
18129202Scognet *
19129202Scognet * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20129202Scognet * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21129202Scognet * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22129202Scognet * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23129202Scognet * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24129202Scognet * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25129202Scognet * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26129202Scognet * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27129202Scognet * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28129202Scognet * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29129202Scognet * POSSIBILITY OF SUCH DAMAGE.
30129202Scognet */
31129202Scognet
32129202Scognet#include <machine/asm.h>
33129202Scognet__FBSDID("$FreeBSD$");
34129202Scognet
35275256Sandrew.syntax	unified
36275256Sandrew
37129202Scognet#ifndef _BCOPY
38129202Scognet/* LINTSTUB: Func: void *memmove(void *, const void *, size_t) */
39129202ScognetENTRY(memmove)
40129202Scognet#else
41129202Scognet/* bcopy = memcpy/memmove with arguments reversed. */
42129202Scognet/* LINTSTUB: Func: void bcopy(void *, void *, size_t) */
43129202ScognetENTRY(bcopy)
44129202Scognet	/* switch the source and destination registers */
45129202Scognet	eor     r0, r1, r0
46129202Scognet	eor     r1, r0, r1
47129202Scognet	eor     r0, r1, r0
48129202Scognet#endif
49129202Scognet	/* Do the buffers overlap? */
50129202Scognet	cmp	r0, r1
51283831Sandrew	it	eq
52137464Scognet	RETeq		/* Bail now if src/dst are the same */
53283831Sandrew	ite	cc
54129202Scognet	subcc	r3, r0, r1	/* if (dst > src) r3 = dst - src */
55129202Scognet	subcs	r3, r1, r0	/* if (src > dsr) r3 = src - dst */
56129202Scognet	cmp	r3, r2		/* if (r3 < len) we have an overlap */
57129202Scognet	bcc	PIC_SYM(_C_LABEL(memcpy), PLT)
58129202Scognet
59129202Scognet	/* Determine copy direction */
60129202Scognet	cmp	r1, r0
61283831Sandrew	it	cc
62129202Scognet	bcc	.Lmemmove_backwards
63129202Scognet
64283831Sandrew	itt	eq
65129202Scognet	moveq	r0, #0			/* Quick abort for len=0 */
66137464Scognet	RETeq
67129202Scognet
68129202Scognet	stmdb	sp!, {r0, lr}		/* memmove() returns dest addr */
69129202Scognet	subs	r2, r2, #4
70129202Scognet	blt	.Lmemmove_fl4		/* less than 4 bytes */
71129202Scognet	ands	r12, r0, #3
72129202Scognet	bne	.Lmemmove_fdestul	/* oh unaligned destination addr */
73129202Scognet	ands	r12, r1, #3
74129202Scognet	bne	.Lmemmove_fsrcul		/* oh unaligned source addr */
75129202Scognet
76129202Scognet.Lmemmove_ft8:
77129202Scognet	/* We have aligned source and destination */
78129202Scognet	subs	r2, r2, #8
79129202Scognet	blt	.Lmemmove_fl12		/* less than 12 bytes (4 from above) */
80129202Scognet	subs	r2, r2, #0x14
81129202Scognet	blt	.Lmemmove_fl32		/* less than 32 bytes (12 from above) */
82129202Scognet	stmdb	sp!, {r4}		/* borrow r4 */
83129202Scognet
84129202Scognet	/* blat 32 bytes at a time */
85129202Scognet	/* XXX for really big copies perhaps we should use more registers */
86129202Scognet.Lmemmove_floop32:
87129202Scognet	ldmia	r1!, {r3, r4, r12, lr}
88129202Scognet	stmia	r0!, {r3, r4, r12, lr}
89129202Scognet	ldmia	r1!, {r3, r4, r12, lr}
90129202Scognet	stmia	r0!, {r3, r4, r12, lr}
91129202Scognet	subs	r2, r2, #0x20
92129202Scognet	bge	.Lmemmove_floop32
93129202Scognet
94129202Scognet	cmn	r2, #0x10
95283831Sandrew	ittt	ge
96275256Sandrew	ldmiage	r1!, {r3, r4, r12, lr}	/* blat a remaining 16 bytes */
97275256Sandrew	stmiage	r0!, {r3, r4, r12, lr}
98129202Scognet	subge	r2, r2, #0x10
99129202Scognet	ldmia	sp!, {r4}		/* return r4 */
100129202Scognet
101129202Scognet.Lmemmove_fl32:
102129202Scognet	adds	r2, r2, #0x14
103129202Scognet
104129202Scognet	/* blat 12 bytes at a time */
105129202Scognet.Lmemmove_floop12:
106283831Sandrew	ittt	ge
107275256Sandrew	ldmiage	r1!, {r3, r12, lr}
108275256Sandrew	stmiage	r0!, {r3, r12, lr}
109275256Sandrew	subsge	r2, r2, #0x0c
110129202Scognet	bge	.Lmemmove_floop12
111129202Scognet
112129202Scognet.Lmemmove_fl12:
113129202Scognet	adds	r2, r2, #8
114129202Scognet	blt	.Lmemmove_fl4
115129202Scognet
116129202Scognet	subs	r2, r2, #4
117283831Sandrew	itt	lt
118129202Scognet	ldrlt	r3, [r1], #4
119129202Scognet	strlt	r3, [r0], #4
120283831Sandrew	ittt	ge
121275256Sandrew	ldmiage	r1!, {r3, r12}
122275256Sandrew	stmiage	r0!, {r3, r12}
123129202Scognet	subge	r2, r2, #4
124129202Scognet
125129202Scognet.Lmemmove_fl4:
126129202Scognet	/* less than 4 bytes to go */
127129202Scognet	adds	r2, r2, #4
128283831Sandrew	it	eq
129275256Sandrew	ldmiaeq	sp!, {r0, pc}		/* done */
130129202Scognet
131129202Scognet	/* copy the crud byte at a time */
132129202Scognet	cmp	r2, #2
133129202Scognet	ldrb	r3, [r1], #1
134129202Scognet	strb	r3, [r0], #1
135283831Sandrew	itt	ge
136275256Sandrew	ldrbge	r3, [r1], #1
137275256Sandrew	strbge	r3, [r0], #1
138283831Sandrew	itt	gt
139275256Sandrew	ldrbgt	r3, [r1], #1
140275256Sandrew	strbgt	r3, [r0], #1
141129202Scognet	ldmia	sp!, {r0, pc}
142129202Scognet
143129202Scognet	/* erg - unaligned destination */
144129202Scognet.Lmemmove_fdestul:
145129202Scognet	rsb	r12, r12, #4
146129202Scognet	cmp	r12, #2
147129202Scognet
148129202Scognet	/* align destination with byte copies */
149129202Scognet	ldrb	r3, [r1], #1
150129202Scognet	strb	r3, [r0], #1
151283831Sandrew	itt	ge
152275256Sandrew	ldrbge	r3, [r1], #1
153275256Sandrew	strbge	r3, [r0], #1
154283831Sandrew	itt	gt
155275256Sandrew	ldrbgt	r3, [r1], #1
156275256Sandrew	strbgt	r3, [r0], #1
157129202Scognet	subs	r2, r2, r12
158129202Scognet	blt	.Lmemmove_fl4		/* less the 4 bytes */
159129202Scognet
160129202Scognet	ands	r12, r1, #3
161129202Scognet	beq	.Lmemmove_ft8		/* we have an aligned source */
162129202Scognet
163129202Scognet	/* erg - unaligned source */
164129202Scognet	/* This is where it gets nasty ... */
165129202Scognet.Lmemmove_fsrcul:
166129202Scognet	bic	r1, r1, #3
167129202Scognet	ldr	lr, [r1], #4
168129202Scognet	cmp	r12, #2
169129202Scognet	bgt	.Lmemmove_fsrcul3
170129202Scognet	beq	.Lmemmove_fsrcul2
171129202Scognet	cmp	r2, #0x0c
172129202Scognet	blt	.Lmemmove_fsrcul1loop4
173129202Scognet	sub	r2, r2, #0x0c
174129202Scognet	stmdb	sp!, {r4, r5}
175129202Scognet
176129202Scognet.Lmemmove_fsrcul1loop16:
177129202Scognet#ifdef __ARMEB__
178129202Scognet	mov	r3, lr, lsl #8
179129202Scognet#else
180129202Scognet	mov	r3, lr, lsr #8
181129202Scognet#endif
182129202Scognet	ldmia	r1!, {r4, r5, r12, lr}
183129202Scognet#ifdef __ARMEB__
184129202Scognet	orr	r3, r3, r4, lsr #24
185129202Scognet	mov	r4, r4, lsl #8
186129202Scognet	orr	r4, r4, r5, lsr #24
187129202Scognet	mov	r5, r5, lsl #8
188129202Scognet	orr	r5, r5, r12, lsr #24
189129202Scognet	mov	r12, r12, lsl #8
190129202Scognet	orr	r12, r12, lr, lsr #24
191129202Scognet#else
192129202Scognet	orr	r3, r3, r4, lsl #24
193129202Scognet	mov	r4, r4, lsr #8
194129202Scognet	orr	r4, r4, r5, lsl #24
195129202Scognet	mov	r5, r5, lsr #8
196129202Scognet	orr	r5, r5, r12, lsl #24
197129202Scognet	mov	r12, r12, lsr #8
198129202Scognet	orr	r12, r12, lr, lsl #24
199129202Scognet#endif
200129202Scognet	stmia	r0!, {r3-r5, r12}
201129202Scognet	subs	r2, r2, #0x10
202129202Scognet	bge	.Lmemmove_fsrcul1loop16
203129202Scognet	ldmia	sp!, {r4, r5}
204129202Scognet	adds	r2, r2, #0x0c
205129202Scognet	blt	.Lmemmove_fsrcul1l4
206129202Scognet
207129202Scognet.Lmemmove_fsrcul1loop4:
208129202Scognet#ifdef __ARMEB__
209129202Scognet	mov	r12, lr, lsl #8
210129202Scognet#else
211129202Scognet	mov	r12, lr, lsr #8
212129202Scognet#endif
213129202Scognet	ldr	lr, [r1], #4
214129202Scognet#ifdef __ARMEB__
215129202Scognet	orr	r12, r12, lr, lsr #24
216129202Scognet#else
217129202Scognet	orr	r12, r12, lr, lsl #24
218129202Scognet#endif
219129202Scognet	str	r12, [r0], #4
220129202Scognet	subs	r2, r2, #4
221129202Scognet	bge	.Lmemmove_fsrcul1loop4
222129202Scognet
223129202Scognet.Lmemmove_fsrcul1l4:
224129202Scognet	sub	r1, r1, #3
225129202Scognet	b	.Lmemmove_fl4
226129202Scognet
227129202Scognet.Lmemmove_fsrcul2:
228129202Scognet	cmp	r2, #0x0c
229129202Scognet	blt	.Lmemmove_fsrcul2loop4
230129202Scognet	sub	r2, r2, #0x0c
231129202Scognet	stmdb	sp!, {r4, r5}
232129202Scognet
233129202Scognet.Lmemmove_fsrcul2loop16:
234129202Scognet#ifdef __ARMEB__
235129202Scognet	mov	r3, lr, lsl #16
236129202Scognet#else
237129202Scognet	mov	r3, lr, lsr #16
238129202Scognet#endif
239129202Scognet	ldmia	r1!, {r4, r5, r12, lr}
240129202Scognet#ifdef __ARMEB__
241129202Scognet	orr	r3, r3, r4, lsr #16
242129202Scognet	mov	r4, r4, lsl #16
243129202Scognet	orr	r4, r4, r5, lsr #16
244129202Scognet	mov	r5, r5, lsl #16
245129202Scognet	orr	r5, r5, r12, lsr #16
246129202Scognet	mov	r12, r12, lsl #16
247129202Scognet	orr	r12, r12, lr, lsr #16
248129202Scognet#else
249129202Scognet	orr	r3, r3, r4, lsl #16
250129202Scognet	mov	r4, r4, lsr #16
251129202Scognet	orr	r4, r4, r5, lsl #16
252129202Scognet	mov	r5, r5, lsr #16
253129202Scognet	orr	r5, r5, r12, lsl #16
254129202Scognet	mov	r12, r12, lsr #16
255129202Scognet	orr	r12, r12, lr, lsl #16
256129202Scognet#endif
257129202Scognet	stmia	r0!, {r3-r5, r12}
258129202Scognet	subs	r2, r2, #0x10
259129202Scognet	bge	.Lmemmove_fsrcul2loop16
260129202Scognet	ldmia	sp!, {r4, r5}
261129202Scognet	adds	r2, r2, #0x0c
262129202Scognet	blt	.Lmemmove_fsrcul2l4
263129202Scognet
264129202Scognet.Lmemmove_fsrcul2loop4:
265129202Scognet#ifdef __ARMEB__
266129202Scognet	mov	r12, lr, lsl #16
267129202Scognet#else
268129202Scognet	mov	r12, lr, lsr #16
269129202Scognet#endif
270129202Scognet	ldr	lr, [r1], #4
271129202Scognet#ifdef __ARMEB__
272129202Scognet	orr	r12, r12, lr, lsr #16
273129202Scognet#else
274129202Scognet	orr	r12, r12, lr, lsl #16
275129202Scognet#endif
276129202Scognet	str	r12, [r0], #4
277129202Scognet	subs	r2, r2, #4
278129202Scognet	bge	.Lmemmove_fsrcul2loop4
279129202Scognet
280129202Scognet.Lmemmove_fsrcul2l4:
281129202Scognet	sub	r1, r1, #2
282129202Scognet	b	.Lmemmove_fl4
283129202Scognet
284129202Scognet.Lmemmove_fsrcul3:
285129202Scognet	cmp	r2, #0x0c
286129202Scognet	blt	.Lmemmove_fsrcul3loop4
287129202Scognet	sub	r2, r2, #0x0c
288129202Scognet	stmdb	sp!, {r4, r5}
289129202Scognet
290129202Scognet.Lmemmove_fsrcul3loop16:
291129202Scognet#ifdef __ARMEB__
292129202Scognet	mov	r3, lr, lsl #24
293129202Scognet#else
294129202Scognet	mov	r3, lr, lsr #24
295129202Scognet#endif
296129202Scognet	ldmia	r1!, {r4, r5, r12, lr}
297129202Scognet#ifdef __ARMEB__
298129202Scognet	orr	r3, r3, r4, lsr #8
299129202Scognet	mov	r4, r4, lsl #24
300129202Scognet	orr	r4, r4, r5, lsr #8
301129202Scognet	mov	r5, r5, lsl #24
302129202Scognet	orr	r5, r5, r12, lsr #8
303129202Scognet	mov	r12, r12, lsl #24
304129202Scognet	orr	r12, r12, lr, lsr #8
305129202Scognet#else
306129202Scognet	orr	r3, r3, r4, lsl #8
307129202Scognet	mov	r4, r4, lsr #24
308129202Scognet	orr	r4, r4, r5, lsl #8
309129202Scognet	mov	r5, r5, lsr #24
310129202Scognet	orr	r5, r5, r12, lsl #8
311129202Scognet	mov	r12, r12, lsr #24
312129202Scognet	orr	r12, r12, lr, lsl #8
313129202Scognet#endif
314129202Scognet	stmia	r0!, {r3-r5, r12}
315129202Scognet	subs	r2, r2, #0x10
316129202Scognet	bge	.Lmemmove_fsrcul3loop16
317129202Scognet	ldmia	sp!, {r4, r5}
318129202Scognet	adds	r2, r2, #0x0c
319129202Scognet	blt	.Lmemmove_fsrcul3l4
320129202Scognet
321129202Scognet.Lmemmove_fsrcul3loop4:
322129202Scognet#ifdef __ARMEB__
323129202Scognet	mov	r12, lr, lsl #24
324129202Scognet#else
325129202Scognet	mov	r12, lr, lsr #24
326129202Scognet#endif
327129202Scognet	ldr	lr, [r1], #4
328129202Scognet#ifdef __ARMEB__
329129202Scognet	orr	r12, r12, lr, lsr #8
330129202Scognet#else
331129202Scognet	orr	r12, r12, lr, lsl #8
332129202Scognet#endif
333129202Scognet	str	r12, [r0], #4
334129202Scognet	subs	r2, r2, #4
335129202Scognet	bge	.Lmemmove_fsrcul3loop4
336129202Scognet
337129202Scognet.Lmemmove_fsrcul3l4:
338129202Scognet	sub	r1, r1, #1
339129202Scognet	b	.Lmemmove_fl4
340129202Scognet
341129202Scognet.Lmemmove_backwards:
342129202Scognet	add	r1, r1, r2
343129202Scognet	add	r0, r0, r2
344129202Scognet	subs	r2, r2, #4
345129202Scognet	blt	.Lmemmove_bl4		/* less than 4 bytes */
346129202Scognet	ands	r12, r0, #3
347129202Scognet	bne	.Lmemmove_bdestul	/* oh unaligned destination addr */
348129202Scognet	ands	r12, r1, #3
349129202Scognet	bne	.Lmemmove_bsrcul		/* oh unaligned source addr */
350129202Scognet
351129202Scognet.Lmemmove_bt8:
352129202Scognet	/* We have aligned source and destination */
353129202Scognet	subs	r2, r2, #8
354129202Scognet	blt	.Lmemmove_bl12		/* less than 12 bytes (4 from above) */
355129202Scognet	stmdb	sp!, {r4, lr}
356129202Scognet	subs	r2, r2, #0x14		/* less than 32 bytes (12 from above) */
357129202Scognet	blt	.Lmemmove_bl32
358129202Scognet
359129202Scognet	/* blat 32 bytes at a time */
360129202Scognet	/* XXX for really big copies perhaps we should use more registers */
361129202Scognet.Lmemmove_bloop32:
362129202Scognet	ldmdb	r1!, {r3, r4, r12, lr}
363129202Scognet	stmdb	r0!, {r3, r4, r12, lr}
364129202Scognet	ldmdb	r1!, {r3, r4, r12, lr}
365129202Scognet	stmdb	r0!, {r3, r4, r12, lr}
366129202Scognet	subs	r2, r2, #0x20
367129202Scognet	bge	.Lmemmove_bloop32
368129202Scognet
369129202Scognet.Lmemmove_bl32:
370129202Scognet	cmn	r2, #0x10
371283831Sandrew	ittt	ge
372275256Sandrew	ldmdbge	r1!, {r3, r4, r12, lr}	/* blat a remaining 16 bytes */
373275256Sandrew	stmdbge	r0!, {r3, r4, r12, lr}
374129202Scognet	subge	r2, r2, #0x10
375129202Scognet	adds	r2, r2, #0x14
376283831Sandrew	ittt	ge
377275256Sandrew	ldmdbge	r1!, {r3, r12, lr}	/* blat a remaining 12 bytes */
378275256Sandrew	stmdbge	r0!, {r3, r12, lr}
379129202Scognet	subge	r2, r2, #0x0c
380129202Scognet	ldmia	sp!, {r4, lr}
381129202Scognet
382129202Scognet.Lmemmove_bl12:
383129202Scognet	adds	r2, r2, #8
384129202Scognet	blt	.Lmemmove_bl4
385129202Scognet	subs	r2, r2, #4
386283831Sandrew	itt	lt
387129202Scognet	ldrlt	r3, [r1, #-4]!
388129202Scognet	strlt	r3, [r0, #-4]!
389283831Sandrew	ittt	ge
390275256Sandrew	ldmdbge	r1!, {r3, r12}
391275256Sandrew	stmdbge	r0!, {r3, r12}
392129202Scognet	subge	r2, r2, #4
393129202Scognet
394129202Scognet.Lmemmove_bl4:
395129202Scognet	/* less than 4 bytes to go */
396129202Scognet	adds	r2, r2, #4
397283831Sandrew	it	eq
398137464Scognet	RETeq			/* done */
399129202Scognet
400129202Scognet	/* copy the crud byte at a time */
401129202Scognet	cmp	r2, #2
402129202Scognet	ldrb	r3, [r1, #-1]!
403129202Scognet	strb	r3, [r0, #-1]!
404283831Sandrew	itt	ge
405275256Sandrew	ldrbge	r3, [r1, #-1]!
406275256Sandrew	strbge	r3, [r0, #-1]!
407283831Sandrew	itt	gt
408275256Sandrew	ldrbgt	r3, [r1, #-1]!
409275256Sandrew	strbgt	r3, [r0, #-1]!
410137464Scognet	RET
411129202Scognet
412129202Scognet	/* erg - unaligned destination */
413129202Scognet.Lmemmove_bdestul:
414129202Scognet	cmp	r12, #2
415129202Scognet
416129202Scognet	/* align destination with byte copies */
417129202Scognet	ldrb	r3, [r1, #-1]!
418129202Scognet	strb	r3, [r0, #-1]!
419283831Sandrew	itt	ge
420275256Sandrew	ldrbge	r3, [r1, #-1]!
421275256Sandrew	strbge	r3, [r0, #-1]!
422283831Sandrew	itt	gt
423275256Sandrew	ldrbgt	r3, [r1, #-1]!
424275256Sandrew	strbgt	r3, [r0, #-1]!
425129202Scognet	subs	r2, r2, r12
426129202Scognet	blt	.Lmemmove_bl4		/* less than 4 bytes to go */
427129202Scognet	ands	r12, r1, #3
428129202Scognet	beq	.Lmemmove_bt8		/* we have an aligned source */
429129202Scognet
430129202Scognet	/* erg - unaligned source */
431129202Scognet	/* This is where it gets nasty ... */
432129202Scognet.Lmemmove_bsrcul:
433129202Scognet	bic	r1, r1, #3
434129202Scognet	ldr	r3, [r1, #0]
435129202Scognet	cmp	r12, #2
436129202Scognet	blt	.Lmemmove_bsrcul1
437129202Scognet	beq	.Lmemmove_bsrcul2
438129202Scognet	cmp	r2, #0x0c
439129202Scognet	blt	.Lmemmove_bsrcul3loop4
440129202Scognet	sub	r2, r2, #0x0c
441129202Scognet	stmdb	sp!, {r4, r5, lr}
442129202Scognet
443129202Scognet.Lmemmove_bsrcul3loop16:
444129202Scognet#ifdef __ARMEB__
445129202Scognet	mov	lr, r3, lsr #8
446129202Scognet#else
447129202Scognet	mov	lr, r3, lsl #8
448129202Scognet#endif
449129202Scognet	ldmdb	r1!, {r3-r5, r12}
450129202Scognet#ifdef __ARMEB__
451129202Scognet	orr	lr, lr, r12, lsl #24
452129202Scognet	mov	r12, r12, lsr #8
453129202Scognet	orr	r12, r12, r5, lsl #24
454129202Scognet	mov	r5, r5, lsr #8
455129202Scognet	orr	r5, r5, r4, lsl #24
456129202Scognet	mov	r4, r4, lsr #8
457129202Scognet	orr	r4, r4, r3, lsl #24
458129202Scognet#else
459129202Scognet	orr	lr, lr, r12, lsr #24
460129202Scognet	mov	r12, r12, lsl #8
461129202Scognet	orr	r12, r12, r5, lsr #24
462129202Scognet	mov	r5, r5, lsl #8
463129202Scognet	orr	r5, r5, r4, lsr #24
464129202Scognet	mov	r4, r4, lsl #8
465129202Scognet	orr	r4, r4, r3, lsr #24
466129202Scognet#endif
467129202Scognet	stmdb	r0!, {r4, r5, r12, lr}
468129202Scognet	subs	r2, r2, #0x10
469129202Scognet	bge	.Lmemmove_bsrcul3loop16
470129202Scognet	ldmia	sp!, {r4, r5, lr}
471129202Scognet	adds	r2, r2, #0x0c
472129202Scognet	blt	.Lmemmove_bsrcul3l4
473129202Scognet
474129202Scognet.Lmemmove_bsrcul3loop4:
475129202Scognet#ifdef __ARMEB__
476129202Scognet	mov	r12, r3, lsr #8
477129202Scognet#else
478129202Scognet	mov	r12, r3, lsl #8
479129202Scognet#endif
480129202Scognet	ldr	r3, [r1, #-4]!
481129202Scognet#ifdef __ARMEB__
482129202Scognet	orr	r12, r12, r3, lsl #24
483129202Scognet#else
484129202Scognet	orr	r12, r12, r3, lsr #24
485129202Scognet#endif
486129202Scognet	str	r12, [r0, #-4]!
487129202Scognet	subs	r2, r2, #4
488129202Scognet	bge	.Lmemmove_bsrcul3loop4
489129202Scognet
490129202Scognet.Lmemmove_bsrcul3l4:
491129202Scognet	add	r1, r1, #3
492129202Scognet	b	.Lmemmove_bl4
493129202Scognet
494129202Scognet.Lmemmove_bsrcul2:
495129202Scognet	cmp	r2, #0x0c
496129202Scognet	blt	.Lmemmove_bsrcul2loop4
497129202Scognet	sub	r2, r2, #0x0c
498129202Scognet	stmdb	sp!, {r4, r5, lr}
499129202Scognet
500129202Scognet.Lmemmove_bsrcul2loop16:
501129202Scognet#ifdef __ARMEB__
502129202Scognet	mov	lr, r3, lsr #16
503129202Scognet#else
504129202Scognet	mov	lr, r3, lsl #16
505129202Scognet#endif
506129202Scognet	ldmdb	r1!, {r3-r5, r12}
507129202Scognet#ifdef __ARMEB__
508129202Scognet	orr	lr, lr, r12, lsl #16
509129202Scognet	mov	r12, r12, lsr #16
510129202Scognet	orr	r12, r12, r5, lsl #16
511129202Scognet	mov	r5, r5, lsr #16
512129202Scognet	orr	r5, r5, r4, lsl #16
513129202Scognet	mov	r4, r4, lsr #16
514129202Scognet	orr	r4, r4, r3, lsl #16
515129202Scognet#else
516129202Scognet	orr	lr, lr, r12, lsr #16
517129202Scognet	mov	r12, r12, lsl #16
518129202Scognet	orr	r12, r12, r5, lsr #16
519129202Scognet	mov	r5, r5, lsl #16
520129202Scognet	orr	r5, r5, r4, lsr #16
521129202Scognet	mov	r4, r4, lsl #16
522129202Scognet	orr	r4, r4, r3, lsr #16
523129202Scognet#endif
524129202Scognet	stmdb	r0!, {r4, r5, r12, lr}
525129202Scognet	subs	r2, r2, #0x10
526129202Scognet	bge	.Lmemmove_bsrcul2loop16
527129202Scognet	ldmia	sp!, {r4, r5, lr}
528129202Scognet	adds	r2, r2, #0x0c
529129202Scognet	blt	.Lmemmove_bsrcul2l4
530129202Scognet
531129202Scognet.Lmemmove_bsrcul2loop4:
532129202Scognet#ifdef __ARMEB__
533129202Scognet	mov	r12, r3, lsr #16
534129202Scognet#else
535129202Scognet	mov	r12, r3, lsl #16
536129202Scognet#endif
537129202Scognet	ldr	r3, [r1, #-4]!
538129202Scognet#ifdef __ARMEB__
539129202Scognet	orr	r12, r12, r3, lsl #16
540129202Scognet#else
541129202Scognet	orr	r12, r12, r3, lsr #16
542129202Scognet#endif
543129202Scognet	str	r12, [r0, #-4]!
544129202Scognet	subs	r2, r2, #4
545129202Scognet	bge	.Lmemmove_bsrcul2loop4
546129202Scognet
547129202Scognet.Lmemmove_bsrcul2l4:
548129202Scognet	add	r1, r1, #2
549129202Scognet	b	.Lmemmove_bl4
550129202Scognet
551129202Scognet.Lmemmove_bsrcul1:
552129202Scognet	cmp	r2, #0x0c
553129202Scognet	blt	.Lmemmove_bsrcul1loop4
554129202Scognet	sub	r2, r2, #0x0c
555129202Scognet	stmdb	sp!, {r4, r5, lr}
556129202Scognet
557129202Scognet.Lmemmove_bsrcul1loop32:
558129202Scognet#ifdef __ARMEB__
559129202Scognet	mov	lr, r3, lsr #24
560129202Scognet#else
561129202Scognet	mov	lr, r3, lsl #24
562129202Scognet#endif
563129202Scognet	ldmdb	r1!, {r3-r5, r12}
564129202Scognet#ifdef __ARMEB__
565129202Scognet	orr	lr, lr, r12, lsl #8
566129202Scognet	mov	r12, r12, lsr #24
567129202Scognet	orr	r12, r12, r5, lsl #8
568129202Scognet	mov	r5, r5, lsr #24
569129202Scognet	orr	r5, r5, r4, lsl #8
570129202Scognet	mov	r4, r4, lsr #24
571129202Scognet	orr	r4, r4, r3, lsl #8
572129202Scognet#else
573129202Scognet	orr	lr, lr, r12, lsr #8
574129202Scognet	mov	r12, r12, lsl #24
575129202Scognet	orr	r12, r12, r5, lsr #8
576129202Scognet	mov	r5, r5, lsl #24
577129202Scognet	orr	r5, r5, r4, lsr #8
578129202Scognet	mov	r4, r4, lsl #24
579129202Scognet	orr	r4, r4, r3, lsr #8
580129202Scognet#endif
581129202Scognet	stmdb	r0!, {r4, r5, r12, lr}
582129202Scognet	subs	r2, r2, #0x10
583129202Scognet	bge	.Lmemmove_bsrcul1loop32
584129202Scognet	ldmia	sp!, {r4, r5, lr}
585129202Scognet	adds	r2, r2, #0x0c
586129202Scognet	blt	.Lmemmove_bsrcul1l4
587129202Scognet
588129202Scognet.Lmemmove_bsrcul1loop4:
589129202Scognet#ifdef __ARMEB__
590129202Scognet	mov	r12, r3, lsr #24
591129202Scognet#else
592129202Scognet	mov	r12, r3, lsl #24
593129202Scognet#endif
594129202Scognet	ldr	r3, [r1, #-4]!
595129202Scognet#ifdef __ARMEB__
596129202Scognet	orr	r12, r12, r3, lsl #8
597129202Scognet#else
598129202Scognet	orr	r12, r12, r3, lsr #8
599129202Scognet#endif
600129202Scognet	str	r12, [r0, #-4]!
601129202Scognet	subs	r2, r2, #4
602129202Scognet	bge	.Lmemmove_bsrcul1loop4
603129202Scognet
604129202Scognet.Lmemmove_bsrcul1l4:
605129202Scognet	add	r1, r1, #1
606129202Scognet	b	.Lmemmove_bl4
607270882Sian#ifndef _BCOPY
608270882SianEND(memmove)
609270882Sian#else
610270882SianEND(bcopy)
611270882Sian#endif
612288373Skib
613288373Skib	.section .note.GNU-stack,"",%progbits
614