1/*
2 *  linux/arch/arm/lib/memmove.S
3 *
4 *  Author:	Nicolas Pitre
5 *  Created:	Sep 28, 2005
6 *  Copyright:	(C) MontaVista Software Inc.
7 *
8 *  This program is free software; you can redistribute it and/or modify
9 *  it under the terms of the GNU General Public License version 2 as
10 *  published by the Free Software Foundation.
11 */
12#include "assembler.h"
13
14		.text
15
16/*
17 * Prototype: void *memmove(void *dest, const void *src, size_t n);
18 *
19 * Note:
20 *
21 * If the memory regions don't overlap, we simply branch to memcpy which is
22 * normally a bit faster. Otherwise the copy is done going downwards.  This
23 * is a transposition of the code from copy_template.S but with the copy
24 * occurring in the opposite direction.
25 */
26
27ENTRY(memmove)
28
29		subs	ip, r0, r1
30		cmphi	r2, ip
31		bls	memcpy
32
33		stmfd	sp!, {r0, r4, lr}
34		add	r1, r1, r2
35		add	r0, r0, r2
36		subs	r2, r2, #4
37		blt	8f
38		ands	ip, r0, #3
39	PLD(	pld	[r1, #-4]		)
40		bne	9f
41		ands	ip, r1, #3
42		bne	10f
43
441:		subs	r2, r2, #(28)
45		stmfd	sp!, {r5 - r8}
46		blt	5f
47
48	CALGN(	ands	ip, r0, #31		)
49	CALGN(	sbcnes	r4, ip, r2		)  @ C is always set here
50	CALGN(	bcs	2f			)
51	CALGN(	adr	r4, 6f			)
52	CALGN(	subs	r2, r2, ip		)  @ C is set here
53	CALGN(	rsb	ip, ip, #32		)
54	CALGN(	add	pc, r4, ip		)
55
56	PLD(	pld	[r1, #-4]		)
572:	PLD(	subs	r2, r2, #96		)
58	PLD(	pld	[r1, #-32]		)
59	PLD(	blt	4f			)
60	PLD(	pld	[r1, #-64]		)
61	PLD(	pld	[r1, #-96]		)
62
633:	PLD(	pld	[r1, #-128]		)
644:		ldmdb	r1!, {r3, r4, r5, r6, r7, r8, ip, lr}
65		subs	r2, r2, #32
66		stmdb	r0!, {r3, r4, r5, r6, r7, r8, ip, lr}
67		bge	3b
68	PLD(	cmn	r2, #96			)
69	PLD(	bge	4b			)
70
715:		ands	ip, r2, #28
72		rsb	ip, ip, #32
73		addne	pc, pc, ip		@ C is always clear here
74		b	7f
756:		W(nop)
76		W(ldr)	r3, [r1, #-4]!
77		W(ldr)	r4, [r1, #-4]!
78		W(ldr)	r5, [r1, #-4]!
79		W(ldr)	r6, [r1, #-4]!
80		W(ldr)	r7, [r1, #-4]!
81		W(ldr)	r8, [r1, #-4]!
82		W(ldr)	lr, [r1, #-4]!
83
84		add	pc, pc, ip
85		nop
86		W(nop)
87		W(str)	r3, [r0, #-4]!
88		W(str)	r4, [r0, #-4]!
89		W(str)	r5, [r0, #-4]!
90		W(str)	r6, [r0, #-4]!
91		W(str)	r7, [r0, #-4]!
92		W(str)	r8, [r0, #-4]!
93		W(str)	lr, [r0, #-4]!
94
95	CALGN(	bcs	2b			)
96
977:		ldmfd	sp!, {r5 - r8}
98
998:		movs	r2, r2, lsl #31
100		ldrneb	r3, [r1, #-1]!
101		ldrcsb	r4, [r1, #-1]!
102		ldrcsb	ip, [r1, #-1]
103		strneb	r3, [r0, #-1]!
104		strcsb	r4, [r0, #-1]!
105		strcsb	ip, [r0, #-1]
106		ldmfd	sp!, {r0, r4, pc}
107
1089:		cmp	ip, #2
109		ldrgtb	r3, [r1, #-1]!
110		ldrgeb	r4, [r1, #-1]!
111		ldrb	lr, [r1, #-1]!
112		strgtb	r3, [r0, #-1]!
113		strgeb	r4, [r0, #-1]!
114		subs	r2, r2, ip
115		strb	lr, [r0, #-1]!
116		blt	8b
117		ands	ip, r1, #3
118		beq	1b
119
12010:		bic	r1, r1, #3
121		cmp	ip, #2
122		ldr	r3, [r1, #0]
123		beq	17f
124		blt	18f
125
126
127		.macro	backward_copy_shift push pull
128
129		subs	r2, r2, #28
130		blt	14f
131
132	CALGN(	ands	ip, r0, #31		)
133	CALGN(	sbcnes	r4, ip, r2		)  @ C is always set here
134	CALGN(	subcc	r2, r2, ip		)
135	CALGN(	bcc	15f			)
136
13711:		stmfd	sp!, {r5 - r9}
138
139	PLD(	pld	[r1, #-4]		)
140	PLD(	subs	r2, r2, #96		)
141	PLD(	pld	[r1, #-32]		)
142	PLD(	blt	13f			)
143	PLD(	pld	[r1, #-64]		)
144	PLD(	pld	[r1, #-96]		)
145
14612:	PLD(	pld	[r1, #-128]		)
14713:		ldmdb   r1!, {r7, r8, r9, ip}
148		mov     lr, r3, lspush #\push
149		subs    r2, r2, #32
150		ldmdb   r1!, {r3, r4, r5, r6}
151		orr     lr, lr, ip, lspull #\pull
152		mov     ip, ip, lspush #\push
153		orr     ip, ip, r9, lspull #\pull
154		mov     r9, r9, lspush #\push
155		orr     r9, r9, r8, lspull #\pull
156		mov     r8, r8, lspush #\push
157		orr     r8, r8, r7, lspull #\pull
158		mov     r7, r7, lspush #\push
159		orr     r7, r7, r6, lspull #\pull
160		mov     r6, r6, lspush #\push
161		orr     r6, r6, r5, lspull #\pull
162		mov     r5, r5, lspush #\push
163		orr     r5, r5, r4, lspull #\pull
164		mov     r4, r4, lspush #\push
165		orr     r4, r4, r3, lspull #\pull
166		stmdb   r0!, {r4 - r9, ip, lr}
167		bge	12b
168	PLD(	cmn	r2, #96			)
169	PLD(	bge	13b			)
170
171		ldmfd	sp!, {r5 - r9}
172
17314:		ands	ip, r2, #28
174		beq	16f
175
17615:		mov     lr, r3, lspush #\push
177		ldr	r3, [r1, #-4]!
178		subs	ip, ip, #4
179		orr	lr, lr, r3, lspull #\pull
180		str	lr, [r0, #-4]!
181		bgt	15b
182	CALGN(	cmp	r2, #0			)
183	CALGN(	bge	11b			)
184
18516:		add	r1, r1, #(\pull / 8)
186		b	8b
187
188		.endm
189
190
191		backward_copy_shift	push=8	pull=24
192
19317:		backward_copy_shift	push=16	pull=16
194
19518:		backward_copy_shift	push=24	pull=8
196
197ENDPROC(memmove)
198