xref: /openbmc/linux/arch/arm/lib/memmove.S (revision 87c2ce3b)
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
13#include <linux/linkage.h>
14#include <asm/assembler.h>
15
16/*
17 * This can be used to enable code to cacheline align the source pointer.
18 * Experiments on tested architectures (StrongARM and XScale) didn't show
19 * this a worthwhile thing to do.  That might be different in the future.
20 */
21//#define CALGN(code...)        code
22#define CALGN(code...)
23
24		.text
25
26/*
27 * Prototype: void *memmove(void *dest, const void *src, size_t n);
28 *
29 * Note:
30 *
31 * If the memory regions don't overlap, we simply branch to memcpy which is
32 * normally a bit faster. Otherwise the copy is done going downwards.  This
33 * is a transposition of the code from copy_template.S but with the copy
34 * occurring in the opposite direction.
35 */
36
37ENTRY(memmove)
38
39		subs	ip, r0, r1
40		cmphi	r2, ip
41		bls	memcpy
42
43		stmfd	sp!, {r0, r4, lr}
44		add	r1, r1, r2
45		add	r0, r0, r2
46		subs	r2, r2, #4
47		blt	8f
48		ands	ip, r0, #3
49	PLD(	pld	[r1, #-4]		)
50		bne	9f
51		ands	ip, r1, #3
52		bne	10f
53
541:		subs	r2, r2, #(28)
55		stmfd	sp!, {r5 - r8}
56		blt	5f
57
58	CALGN(	ands	ip, r1, #31		)
59	CALGN(	sbcnes	r4, ip, r2		)  @ C is always set here
60	CALGN(	bcs	2f			)
61	CALGN(	adr	r4, 6f			)
62	CALGN(	subs	r2, r2, ip		)  @ C is set here
63	CALGN(	add	pc, r4, ip		)
64
65	PLD(	pld	[r1, #-4]		)
662:	PLD(	subs	r2, r2, #96		)
67	PLD(	pld	[r1, #-32]		)
68	PLD(	blt	4f			)
69	PLD(	pld	[r1, #-64]		)
70	PLD(	pld	[r1, #-96]		)
71
723:	PLD(	pld	[r1, #-128]		)
734:		ldmdb	r1!, {r3, r4, r5, r6, r7, r8, ip, lr}
74		subs	r2, r2, #32
75		stmdb	r0!, {r3, r4, r5, r6, r7, r8, ip, lr}
76		bge	3b
77	PLD(	cmn	r2, #96			)
78	PLD(	bge	4b			)
79
805:		ands	ip, r2, #28
81		rsb	ip, ip, #32
82		addne	pc, pc, ip		@ C is always clear here
83		b	7f
846:		nop
85		ldr	r3, [r1, #-4]!
86		ldr	r4, [r1, #-4]!
87		ldr	r5, [r1, #-4]!
88		ldr	r6, [r1, #-4]!
89		ldr	r7, [r1, #-4]!
90		ldr	r8, [r1, #-4]!
91		ldr	lr, [r1, #-4]!
92
93		add	pc, pc, ip
94		nop
95		nop
96		str	r3, [r0, #-4]!
97		str	r4, [r0, #-4]!
98		str	r5, [r0, #-4]!
99		str	r6, [r0, #-4]!
100		str	r7, [r0, #-4]!
101		str	r8, [r0, #-4]!
102		str	lr, [r0, #-4]!
103
104	CALGN(	bcs	2b			)
105
1067:		ldmfd	sp!, {r5 - r8}
107
1088:		movs	r2, r2, lsl #31
109		ldrneb	r3, [r1, #-1]!
110		ldrcsb	r4, [r1, #-1]!
111		ldrcsb	ip, [r1, #-1]
112		strneb	r3, [r0, #-1]!
113		strcsb	r4, [r0, #-1]!
114		strcsb	ip, [r0, #-1]
115		ldmfd	sp!, {r0, r4, pc}
116
1179:		cmp	ip, #2
118		ldrgtb	r3, [r1, #-1]!
119		ldrgeb	r4, [r1, #-1]!
120		ldrb	lr, [r1, #-1]!
121		strgtb	r3, [r0, #-1]!
122		strgeb	r4, [r0, #-1]!
123		subs	r2, r2, ip
124		strb	lr, [r0, #-1]!
125		blt	8b
126		ands	ip, r1, #3
127		beq	1b
128
12910:		bic	r1, r1, #3
130		cmp	ip, #2
131		ldr	r3, [r1, #0]
132		beq	17f
133		blt	18f
134
135
136		.macro	backward_copy_shift push pull
137
138		subs	r2, r2, #28
139		blt	14f
140
141	CALGN(	ands	ip, r1, #31		)
142	CALGN(	rsb	ip, ip, #32		)
143	CALGN(	sbcnes	r4, ip, r2		)  @ C is always set here
144	CALGN(	subcc	r2, r2, ip		)
145	CALGN(	bcc	15f			)
146
14711:		stmfd	sp!, {r5 - r9}
148
149	PLD(	pld	[r1, #-4]		)
150	PLD(	subs	r2, r2, #96		)
151	PLD(	pld	[r1, #-32]		)
152	PLD(	blt	13f			)
153	PLD(	pld	[r1, #-64]		)
154	PLD(	pld	[r1, #-96]		)
155
15612:	PLD(	pld	[r1, #-128]		)
15713:		ldmdb   r1!, {r7, r8, r9, ip}
158		mov     lr, r3, push #\push
159		subs    r2, r2, #32
160		ldmdb   r1!, {r3, r4, r5, r6}
161		orr     lr, lr, ip, pull #\pull
162		mov     ip, ip, push #\push
163		orr     ip, ip, r9, pull #\pull
164		mov     r9, r9, push #\push
165		orr     r9, r9, r8, pull #\pull
166		mov     r8, r8, push #\push
167		orr     r8, r8, r7, pull #\pull
168		mov     r7, r7, push #\push
169		orr     r7, r7, r6, pull #\pull
170		mov     r6, r6, push #\push
171		orr     r6, r6, r5, pull #\pull
172		mov     r5, r5, push #\push
173		orr     r5, r5, r4, pull #\pull
174		mov     r4, r4, push #\push
175		orr     r4, r4, r3, pull #\pull
176		stmdb   r0!, {r4 - r9, ip, lr}
177		bge	12b
178	PLD(	cmn	r2, #96			)
179	PLD(	bge	13b			)
180
181		ldmfd	sp!, {r5 - r9}
182
18314:		ands	ip, r2, #28
184		beq	16f
185
18615:		mov     lr, r3, push #\push
187		ldr	r3, [r1, #-4]!
188		subs	ip, ip, #4
189		orr	lr, lr, r3, pull #\pull
190		str	lr, [r0, #-4]!
191		bgt	15b
192	CALGN(	cmp	r2, #0			)
193	CALGN(	bge	11b			)
194
19516:		add	r1, r1, #(\pull / 8)
196		b	8b
197
198		.endm
199
200
201		backward_copy_shift	push=8	pull=24
202
20317:		backward_copy_shift	push=16	pull=16
204
20518:		backward_copy_shift	push=24	pull=8
206
207