1 /* SPDX-License-Identifier: GPL-2.0-only */ !! 1 /* memmove.S: Simple memmove implementation. 2 /* << 3 * linux/arch/arm/lib/memmove.S << 4 * 2 * 5 * Author: Nicolas Pitre !! 3 * Copyright (C) 1997, 2004 David S. Miller (davem@redhat.com) 6 * Created: Sep 28, 2005 !! 4 * Copyright (C) 1996, 1997, 1998, 1999 Jakub Jelinek (jj@ultra.linux.cz) 7 * Copyright: (C) MontaVista Software Inc. << 8 */ 5 */ 9 6 10 #include <linux/linkage.h> 7 #include <linux/linkage.h> 11 #include <asm/assembler.h> !! 8 #include <asm/export.h> 12 #include <asm/unwind.h> << 13 9 14 .text !! 10 .text 15 !! 11 ENTRY(memmove) /* o0=dst o1=src o2=len */ 16 /* !! 12 brz,pn %o2, 99f 17 * Prototype: void *memmove(void *dest, const !! 13 mov %o0, %g1 18 * !! 14 19 * Note: !! 15 cmp %o0, %o1 20 * !! 16 bleu,pt %xcc, 2f 21 * If the memory regions don't overlap, we sim !! 17 add %o1, %o2, %g7 22 * normally a bit faster. Otherwise the copy i !! 18 cmp %g7, %o0 23 * is a transposition of the code from copy_te !! 19 bleu,pt %xcc, memcpy 24 * occurring in the opposite direction. !! 20 add %o0, %o2, %o5 25 */ !! 21 sub %g7, 1, %o1 26 !! 22 27 ENTRY(__memmove) !! 23 sub %o5, 1, %o0 28 WEAK(memmove) !! 24 1: ldub [%o1], %g7 29 UNWIND( .fnstart !! 25 subcc %o2, 1, %o2 30 !! 26 sub %o1, 1, %o1 31 subs ip, r0, r1 !! 27 stb %g7, [%o0] 32 cmphi r2, ip !! 28 bne,pt %icc, 1b 33 bls __memcpy !! 29 sub %o0, 1, %o0 34 UNWIND( .fnend !! 30 99: 35 !! 31 retl 36 UNWIND( .fnstart !! 32 mov %g1, %o0 37 UNWIND( .save {r0, r4, fpreg, lr} !! 33 38 stmfd sp!, {r0, r4, UNWIND(f !! 34 /* We can't just call memcpy for these memmove cases. On some 39 UNWIND( .setfp fpreg, sp !! 35 * chips the memcpy uses cache initializing stores and when dst 40 UNWIND( mov fpreg, sp !! 36 * and src are close enough, those can clobber the source data 41 add r1, r1, r2 !! 37 * before we've loaded it in. 42 add r0, r0, r2 !! 38 */ 43 subs r2, r2, #4 !! 39 2: or %o0, %o1, %g7 44 blt 8f !! 40 or %o2, %g7, %g7 45 ands ip, r0, #3 !! 41 andcc %g7, 0x7, %g0 46 PLD( pld [r1, #-4] !! 42 bne,pn %xcc, 4f 47 bne 9f !! 43 nop 48 ands ip, r1, #3 !! 44 49 bne 10f !! 45 3: ldx [%o1], %g7 50 !! 46 add %o1, 8, %o1 51 1: subs r2, r2, #(28) !! 47 subcc %o2, 8, %o2 52 stmfd sp!, {r5, r6, r8, r9} !! 48 add %o0, 8, %o0 53 blt 5f !! 49 bne,pt %icc, 3b 54 !! 50 stx %g7, [%o0 - 0x8] 55 CALGN( ands ip, r0, #31 !! 51 ba,a,pt %xcc, 99b 56 CALGN( sbcsne r4, ip, r2 !! 52 57 CALGN( bcs 2f !! 53 4: ldub [%o1], %g7 58 CALGN( adr r4, 6f !! 54 add %o1, 1, %o1 59 CALGN( subs r2, r2, ip !! 55 subcc %o2, 1, %o2 60 CALGN( rsb ip, ip, #32 !! 56 add %o0, 1, %o0 61 CALGN( add pc, r4, ip !! 57 bne,pt %icc, 4b 62 !! 58 stb %g7, [%o0 - 0x1] 63 PLD( pld [r1, #-4] !! 59 ba,a,pt %xcc, 99b 64 2: PLD( subs r2, r2, #96 << 65 PLD( pld [r1, #-32] << 66 PLD( blt 4f << 67 PLD( pld [r1, #-64] << 68 PLD( pld [r1, #-96] << 69 << 70 3: PLD( pld [r1, #-128] << 71 4: ldmdb r1!, {r3, r4, r5, r6, << 72 subs r2, r2, #32 << 73 stmdb r0!, {r3, r4, r5, r6, << 74 bge 3b << 75 PLD( cmn r2, #96 << 76 PLD( bge 4b << 77 << 78 5: ands ip, r2, #28 << 79 rsb ip, ip, #32 << 80 addne pc, pc, ip << 81 b 7f << 82 6: W(nop) << 83 W(ldr) r3, [r1, #-4]! << 84 W(ldr) r4, [r1, #-4]! << 85 W(ldr) r5, [r1, #-4]! << 86 W(ldr) r6, [r1, #-4]! << 87 W(ldr) r8, [r1, #-4]! << 88 W(ldr) r9, [r1, #-4]! << 89 W(ldr) lr, [r1, #-4]! << 90 << 91 add pc, pc, ip << 92 nop << 93 W(nop) << 94 W(str) r3, [r0, #-4]! << 95 W(str) r4, [r0, #-4]! << 96 W(str) r5, [r0, #-4]! << 97 W(str) r6, [r0, #-4]! << 98 W(str) r8, [r0, #-4]! << 99 W(str) r9, [r0, #-4]! << 100 W(str) lr, [r0, #-4]! << 101 << 102 CALGN( bcs 2b << 103 << 104 7: ldmfd sp!, {r5, r6, r8, r9} << 105 << 106 8: movs r2, r2, lsl #31 << 107 ldrbne r3, [r1, #-1]! << 108 ldrbcs r4, [r1, #-1]! << 109 ldrbcs ip, [r1, #-1] << 110 strbne r3, [r0, #-1]! << 111 strbcs r4, [r0, #-1]! << 112 strbcs ip, [r0, #-1] << 113 ldmfd sp!, {r0, r4, UNWIND(f << 114 << 115 9: cmp ip, #2 << 116 ldrbgt r3, [r1, #-1]! << 117 ldrbge r4, [r1, #-1]! << 118 ldrb lr, [r1, #-1]! << 119 strbgt r3, [r0, #-1]! << 120 strbge r4, [r0, #-1]! << 121 subs r2, r2, ip << 122 strb lr, [r0, #-1]! << 123 blt 8b << 124 ands ip, r1, #3 << 125 beq 1b << 126 << 127 10: bic r1, r1, #3 << 128 cmp ip, #2 << 129 ldr r3, [r1, #0] << 130 beq 17f << 131 blt 18f << 132 << 133 << 134 .macro backward_copy_shift pu << 135 << 136 subs r2, r2, #28 << 137 blt 14f << 138 << 139 CALGN( ands ip, r0, #31 << 140 CALGN( sbcsne r4, ip, r2 << 141 CALGN( subcc r2, r2, ip << 142 CALGN( bcc 15f << 143 << 144 11: stmfd sp!, {r5, r6, r8 - r10 << 145 << 146 PLD( pld [r1, #-4] << 147 PLD( subs r2, r2, #96 << 148 PLD( pld [r1, #-32] << 149 PLD( blt 13f << 150 PLD( pld [r1, #-64] << 151 PLD( pld [r1, #-96] << 152 << 153 12: PLD( pld [r1, #-128] << 154 13: ldmdb r1!, {r8, r9, r10, ip} << 155 mov lr, r3, lspush #\push << 156 subs r2, r2, #32 << 157 ldmdb r1!, {r3, r4, r5, r6} << 158 orr lr, lr, ip, lspull #\p << 159 mov ip, ip, lspush #\push << 160 orr ip, ip, r10, lspull #\ << 161 mov r10, r10, lspush #\pus << 162 orr r10, r10, r9, lspull # << 163 mov r9, r9, lspush #\push << 164 orr r9, r9, r8, lspull #\p << 165 mov r8, r8, lspush #\push << 166 orr r8, r8, r6, lspull #\p << 167 mov r6, r6, lspush #\push << 168 orr r6, r6, r5, lspull #\p << 169 mov r5, r5, lspush #\push << 170 orr r5, r5, r4, lspull #\p << 171 mov r4, r4, lspush #\push << 172 orr r4, r4, r3, lspull #\p << 173 stmdb r0!, {r4 - r6, r8 - r1 << 174 bge 12b << 175 PLD( cmn r2, #96 << 176 PLD( bge 13b << 177 << 178 ldmfd sp!, {r5, r6, r8 - r10 << 179 << 180 14: ands ip, r2, #28 << 181 beq 16f << 182 << 183 15: mov lr, r3, lspush #\push << 184 ldr r3, [r1, #-4]! << 185 subs ip, ip, #4 << 186 orr lr, lr, r3, lspull #\p << 187 str lr, [r0, #-4]! << 188 bgt 15b << 189 CALGN( cmp r2, #0 << 190 CALGN( bge 11b << 191 << 192 16: add r1, r1, #(\pull / 8) << 193 b 8b << 194 << 195 .endm << 196 << 197 << 198 backward_copy_shift push=8 << 199 << 200 17: backward_copy_shift push=1 << 201 << 202 18: backward_copy_shift push=2 << 203 << 204 UNWIND( .fnend << 205 ENDPROC(memmove) 60 ENDPROC(memmove) 206 ENDPROC(__memmove) !! 61 EXPORT_SYMBOL(memmove)
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.