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