^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /* SPDX-License-Identifier: GPL-2.0-only */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * linux/arch/arm/lib/memmove.S
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Author: Nicolas Pitre
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Created: Sep 28, 2005
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Copyright: (C) MontaVista Software Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/linkage.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <asm/assembler.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <asm/unwind.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) .text
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * Prototype: void *memmove(void *dest, const void *src, size_t n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * Note:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * If the memory regions don't overlap, we simply branch to memcpy which is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) * normally a bit faster. Otherwise the copy is done going downwards. This
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * is a transposition of the code from copy_template.S but with the copy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * occurring in the opposite direction.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) ENTRY(memmove)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) UNWIND( .fnstart )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) subs ip, r0, r1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) cmphi r2, ip
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) bls memcpy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) stmfd sp!, {r0, r4, lr}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) UNWIND( .fnend )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) UNWIND( .fnstart )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) UNWIND( .save {r0, r4, lr} ) @ in first stmfd block
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) add r1, r1, r2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) add r0, r0, r2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) subs r2, r2, #4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) blt 8f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) ands ip, r0, #3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) PLD( pld [r1, #-4] )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) bne 9f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) ands ip, r1, #3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) bne 10f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) 1: subs r2, r2, #(28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) stmfd sp!, {r5 - r8}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) UNWIND( .fnend )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) UNWIND( .fnstart )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) UNWIND( .save {r0, r4, lr} )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) UNWIND( .save {r5 - r8} ) @ in second stmfd block
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) blt 5f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) CALGN( ands ip, r0, #31 )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) CALGN( sbcsne r4, ip, r2 ) @ C is always set here
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) CALGN( bcs 2f )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) CALGN( adr r4, 6f )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) CALGN( subs r2, r2, ip ) @ C is set here
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) CALGN( rsb ip, ip, #32 )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) CALGN( add pc, r4, ip )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) PLD( pld [r1, #-4] )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) 2: PLD( subs r2, r2, #96 )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) PLD( pld [r1, #-32] )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) PLD( blt 4f )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) PLD( pld [r1, #-64] )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) PLD( pld [r1, #-96] )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) 3: PLD( pld [r1, #-128] )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) 4: ldmdb r1!, {r3, r4, r5, r6, r7, r8, ip, lr}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) subs r2, r2, #32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) stmdb r0!, {r3, r4, r5, r6, r7, r8, ip, lr}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) bge 3b
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) PLD( cmn r2, #96 )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) PLD( bge 4b )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) 5: ands ip, r2, #28
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) rsb ip, ip, #32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) addne pc, pc, ip @ C is always clear here
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) b 7f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) 6: W(nop)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) W(ldr) r3, [r1, #-4]!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) W(ldr) r4, [r1, #-4]!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) W(ldr) r5, [r1, #-4]!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) W(ldr) r6, [r1, #-4]!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) W(ldr) r7, [r1, #-4]!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) W(ldr) r8, [r1, #-4]!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) W(ldr) lr, [r1, #-4]!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) add pc, pc, ip
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) nop
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) W(nop)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) W(str) r3, [r0, #-4]!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) W(str) r4, [r0, #-4]!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) W(str) r5, [r0, #-4]!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) W(str) r6, [r0, #-4]!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) W(str) r7, [r0, #-4]!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) W(str) r8, [r0, #-4]!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) W(str) lr, [r0, #-4]!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) CALGN( bcs 2b )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 7: ldmfd sp!, {r5 - r8}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) UNWIND( .fnend ) @ end of second stmfd block
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) UNWIND( .fnstart )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) UNWIND( .save {r0, r4, lr} ) @ still in first stmfd block
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 8: movs r2, r2, lsl #31
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) ldrbne r3, [r1, #-1]!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) ldrbcs r4, [r1, #-1]!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) ldrbcs ip, [r1, #-1]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) strbne r3, [r0, #-1]!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) strbcs r4, [r0, #-1]!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) strbcs ip, [r0, #-1]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) ldmfd sp!, {r0, r4, pc}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 9: cmp ip, #2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) ldrbgt r3, [r1, #-1]!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) ldrbge r4, [r1, #-1]!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) ldrb lr, [r1, #-1]!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) strbgt r3, [r0, #-1]!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) strbge r4, [r0, #-1]!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) subs r2, r2, ip
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) strb lr, [r0, #-1]!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) blt 8b
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) ands ip, r1, #3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) beq 1b
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 10: bic r1, r1, #3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) cmp ip, #2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) ldr r3, [r1, #0]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) beq 17f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) blt 18f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) UNWIND( .fnend )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) .macro backward_copy_shift push pull
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) UNWIND( .fnstart )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) UNWIND( .save {r0, r4, lr} ) @ still in first stmfd block
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) subs r2, r2, #28
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) blt 14f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) CALGN( ands ip, r0, #31 )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) CALGN( sbcsne r4, ip, r2 ) @ C is always set here
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) CALGN( subcc r2, r2, ip )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) CALGN( bcc 15f )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 11: stmfd sp!, {r5 - r9}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) UNWIND( .fnend )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) UNWIND( .fnstart )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) UNWIND( .save {r0, r4, lr} )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) UNWIND( .save {r5 - r9} ) @ in new second stmfd block
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) PLD( pld [r1, #-4] )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) PLD( subs r2, r2, #96 )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) PLD( pld [r1, #-32] )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) PLD( blt 13f )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) PLD( pld [r1, #-64] )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) PLD( pld [r1, #-96] )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 12: PLD( pld [r1, #-128] )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 13: ldmdb r1!, {r7, r8, r9, ip}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) mov lr, r3, lspush #\push
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) subs r2, r2, #32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) ldmdb r1!, {r3, r4, r5, r6}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) orr lr, lr, ip, lspull #\pull
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) mov ip, ip, lspush #\push
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) orr ip, ip, r9, lspull #\pull
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) mov r9, r9, lspush #\push
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) orr r9, r9, r8, lspull #\pull
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) mov r8, r8, lspush #\push
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) orr r8, r8, r7, lspull #\pull
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) mov r7, r7, lspush #\push
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) orr r7, r7, r6, lspull #\pull
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) mov r6, r6, lspush #\push
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) orr r6, r6, r5, lspull #\pull
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) mov r5, r5, lspush #\push
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) orr r5, r5, r4, lspull #\pull
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) mov r4, r4, lspush #\push
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) orr r4, r4, r3, lspull #\pull
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) stmdb r0!, {r4 - r9, ip, lr}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) bge 12b
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) PLD( cmn r2, #96 )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) PLD( bge 13b )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) ldmfd sp!, {r5 - r9}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) UNWIND( .fnend ) @ end of the second stmfd block
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) UNWIND( .fnstart )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) UNWIND( .save {r0, r4, lr} ) @ still in first stmfd block
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 14: ands ip, r2, #28
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) beq 16f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 15: mov lr, r3, lspush #\push
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) ldr r3, [r1, #-4]!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) subs ip, ip, #4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) orr lr, lr, r3, lspull #\pull
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) str lr, [r0, #-4]!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) bgt 15b
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) CALGN( cmp r2, #0 )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) CALGN( bge 11b )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 16: add r1, r1, #(\pull / 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) b 8b
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) UNWIND( .fnend )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) .endm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) backward_copy_shift push=8 pull=24
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 17: backward_copy_shift push=16 pull=16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 18: backward_copy_shift push=24 pull=8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) ENDPROC(memmove)