1 /* SPDX-License-Identifier: GPL-2.0-only */
3 * linux/arch/arm/lib/memmove.S
5 * Author: Nicolas Pitre
6 * Created: Sep 28, 2005
7 * Copyright: (C) MontaVista Software Inc.
10 #include <linux/linkage.h>
11 #include <asm/assembler.h>
12 #include <asm/unwind.h>
17 * Prototype: void *memmove(void *dest, const void *src, size_t n);
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.
37 UNWIND( .save {r0, r4, fpreg, lr} )
38 stmfd sp!, {r0, r4, UNWIND(fpreg,) lr}
39 UNWIND( .setfp fpreg, sp )
40 UNWIND( mov fpreg, sp )
52 stmfd sp!, {r5, r6, r8, r9}
55 CALGN( ands ip, r0, #31 )
56 CALGN( sbcsne r4, ip, r2 ) @ C is always set here
59 CALGN( subs r2, r2, ip ) @ C is set here
60 CALGN( rsb ip, ip, #32 )
61 CALGN( add pc, r4, ip )
64 2: PLD( subs r2, r2, #96 )
70 3: PLD( pld [r1, #-128] )
71 4: ldmdb r1!, {r3, r4, r5, r6, r8, r9, ip, lr}
73 stmdb r0!, {r3, r4, r5, r6, r8, r9, ip, lr}
80 addne pc, pc, ip @ C is always clear here
100 W(str) lr, [r0, #-4]!
104 7: ldmfd sp!, {r5, r6, r8, r9}
106 8: movs r2, r2, lsl #31
107 ldrbne r3, [r1, #-1]!
108 ldrbcs r4, [r1, #-1]!
110 strbne r3, [r0, #-1]!
111 strbcs r4, [r0, #-1]!
113 ldmfd sp!, {r0, r4, UNWIND(fpreg,) pc}
116 ldrbgt r3, [r1, #-1]!
117 ldrbge r4, [r1, #-1]!
119 strbgt r3, [r0, #-1]!
120 strbge r4, [r0, #-1]!
134 .macro backward_copy_shift push pull
139 CALGN( ands ip, r0, #31 )
140 CALGN( sbcsne r4, ip, r2 ) @ C is always set here
141 CALGN( subcc r2, r2, ip )
144 11: stmfd sp!, {r5, r6, r8 - r10}
147 PLD( subs r2, r2, #96 )
148 PLD( pld [r1, #-32] )
150 PLD( pld [r1, #-64] )
151 PLD( pld [r1, #-96] )
153 12: PLD( pld [r1, #-128] )
154 13: ldmdb r1!, {r8, r9, r10, ip}
155 mov lr, r3, lspush #\push
157 ldmdb r1!, {r3, r4, r5, r6}
158 orr lr, lr, ip, lspull #\pull
159 mov ip, ip, lspush #\push
160 orr ip, ip, r10, lspull #\pull
161 mov r10, r10, lspush #\push
162 orr r10, r10, r9, lspull #\pull
163 mov r9, r9, lspush #\push
164 orr r9, r9, r8, lspull #\pull
165 mov r8, r8, lspush #\push
166 orr r8, r8, r6, lspull #\pull
167 mov r6, r6, lspush #\push
168 orr r6, r6, r5, lspull #\pull
169 mov r5, r5, lspush #\push
170 orr r5, r5, r4, lspull #\pull
171 mov r4, r4, lspush #\push
172 orr r4, r4, r3, lspull #\pull
173 stmdb r0!, {r4 - r6, r8 - r10, ip, lr}
178 ldmfd sp!, {r5, r6, r8 - r10}
183 15: mov lr, r3, lspush #\push
186 orr lr, lr, r3, lspull #\pull
192 16: add r1, r1, #(\pull / 8)
198 backward_copy_shift push=8 pull=24
200 17: backward_copy_shift push=16 pull=16
202 18: backward_copy_shift push=24 pull=8