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 .text 17 18/* 19 * Prototype: void *memmove(void *dest, const void *src, size_t n); 20 * 21 * Note: 22 * 23 * If the memory regions don't overlap, we simply branch to memcpy which is 24 * normally a bit faster. Otherwise the copy is done going downwards. This 25 * is a transposition of the code from copy_template.S but with the copy 26 * occurring in the opposite direction. 27 */ 28 29ENTRY(memmove) 30 31 subs ip, r0, r1 32 cmphi r2, ip 33 bls memcpy 34 35 stmfd sp!, {r0, r4, lr} 36 add r1, r1, r2 37 add r0, r0, r2 38 subs r2, r2, #4 39 blt 8f 40 ands ip, r0, #3 41 PLD( pld [r1, #-4] ) 42 bne 9f 43 ands ip, r1, #3 44 bne 10f 45 461: subs r2, r2, #(28) 47 stmfd sp!, {r5 - r8} 48 blt 5f 49 50 CALGN( ands ip, r0, #31 ) 51 CALGN( sbcnes r4, ip, r2 ) @ C is always set here 52 CALGN( bcs 2f ) 53 CALGN( adr r4, 6f ) 54 CALGN( subs r2, r2, ip ) @ C is set here 55 CALGN( rsb ip, ip, #32 ) 56 CALGN( add pc, r4, ip ) 57 58 PLD( pld [r1, #-4] ) 592: PLD( subs r2, r2, #96 ) 60 PLD( pld [r1, #-32] ) 61 PLD( blt 4f ) 62 PLD( pld [r1, #-64] ) 63 PLD( pld [r1, #-96] ) 64 653: PLD( pld [r1, #-128] ) 664: ldmdb r1!, {r3, r4, r5, r6, r7, r8, ip, lr} 67 subs r2, r2, #32 68 stmdb r0!, {r3, r4, r5, r6, r7, r8, ip, lr} 69 bge 3b 70 PLD( cmn r2, #96 ) 71 PLD( bge 4b ) 72 735: ands ip, r2, #28 74 rsb ip, ip, #32 75 addne pc, pc, ip @ C is always clear here 76 b 7f 776: W(nop) 78 W(ldr) r3, [r1, #-4]! 79 W(ldr) r4, [r1, #-4]! 80 W(ldr) r5, [r1, #-4]! 81 W(ldr) r6, [r1, #-4]! 82 W(ldr) r7, [r1, #-4]! 83 W(ldr) r8, [r1, #-4]! 84 W(ldr) lr, [r1, #-4]! 85 86 add pc, pc, ip 87 nop 88 W(nop) 89 W(str) r3, [r0, #-4]! 90 W(str) r4, [r0, #-4]! 91 W(str) r5, [r0, #-4]! 92 W(str) r6, [r0, #-4]! 93 W(str) r7, [r0, #-4]! 94 W(str) r8, [r0, #-4]! 95 W(str) lr, [r0, #-4]! 96 97 CALGN( bcs 2b ) 98 997: ldmfd sp!, {r5 - r8} 100 1018: movs r2, r2, lsl #31 102 ldrneb r3, [r1, #-1]! 103 ldrcsb r4, [r1, #-1]! 104 ldrcsb ip, [r1, #-1] 105 strneb r3, [r0, #-1]! 106 strcsb r4, [r0, #-1]! 107 strcsb ip, [r0, #-1] 108 ldmfd sp!, {r0, r4, pc} 109 1109: cmp ip, #2 111 ldrgtb r3, [r1, #-1]! 112 ldrgeb r4, [r1, #-1]! 113 ldrb lr, [r1, #-1]! 114 strgtb r3, [r0, #-1]! 115 strgeb r4, [r0, #-1]! 116 subs r2, r2, ip 117 strb lr, [r0, #-1]! 118 blt 8b 119 ands ip, r1, #3 120 beq 1b 121 12210: bic r1, r1, #3 123 cmp ip, #2 124 ldr r3, [r1, #0] 125 beq 17f 126 blt 18f 127 128 129 .macro backward_copy_shift push pull 130 131 subs r2, r2, #28 132 blt 14f 133 134 CALGN( ands ip, r0, #31 ) 135 CALGN( sbcnes r4, ip, r2 ) @ C is always set here 136 CALGN( subcc r2, r2, ip ) 137 CALGN( bcc 15f ) 138 13911: stmfd sp!, {r5 - r9} 140 141 PLD( pld [r1, #-4] ) 142 PLD( subs r2, r2, #96 ) 143 PLD( pld [r1, #-32] ) 144 PLD( blt 13f ) 145 PLD( pld [r1, #-64] ) 146 PLD( pld [r1, #-96] ) 147 14812: PLD( pld [r1, #-128] ) 14913: ldmdb r1!, {r7, r8, r9, ip} 150 mov lr, r3, lspush #\push 151 subs r2, r2, #32 152 ldmdb r1!, {r3, r4, r5, r6} 153 orr lr, lr, ip, lspull #\pull 154 mov ip, ip, lspush #\push 155 orr ip, ip, r9, lspull #\pull 156 mov r9, r9, lspush #\push 157 orr r9, r9, r8, lspull #\pull 158 mov r8, r8, lspush #\push 159 orr r8, r8, r7, lspull #\pull 160 mov r7, r7, lspush #\push 161 orr r7, r7, r6, lspull #\pull 162 mov r6, r6, lspush #\push 163 orr r6, r6, r5, lspull #\pull 164 mov r5, r5, lspush #\push 165 orr r5, r5, r4, lspull #\pull 166 mov r4, r4, lspush #\push 167 orr r4, r4, r3, lspull #\pull 168 stmdb r0!, {r4 - r9, ip, lr} 169 bge 12b 170 PLD( cmn r2, #96 ) 171 PLD( bge 13b ) 172 173 ldmfd sp!, {r5 - r9} 174 17514: ands ip, r2, #28 176 beq 16f 177 17815: mov lr, r3, lspush #\push 179 ldr r3, [r1, #-4]! 180 subs ip, ip, #4 181 orr lr, lr, r3, lspull #\pull 182 str lr, [r0, #-4]! 183 bgt 15b 184 CALGN( cmp r2, #0 ) 185 CALGN( bge 11b ) 186 18716: add r1, r1, #(\pull / 8) 188 b 8b 189 190 .endm 191 192 193 backward_copy_shift push=8 pull=24 194 19517: backward_copy_shift push=16 pull=16 196 19718: backward_copy_shift push=24 pull=8 198 199ENDPROC(memmove) 200