1d2912cb1SThomas Gleixner/* SPDX-License-Identifier: GPL-2.0-only */ 275494230SNicolas Pitre/* 375494230SNicolas Pitre * linux/arch/arm/lib/memmove.S 475494230SNicolas Pitre * 575494230SNicolas Pitre * Author: Nicolas Pitre 675494230SNicolas Pitre * Created: Sep 28, 2005 775494230SNicolas Pitre * Copyright: (C) MontaVista Software Inc. 875494230SNicolas Pitre */ 975494230SNicolas Pitre 1075494230SNicolas Pitre#include <linux/linkage.h> 1175494230SNicolas Pitre#include <asm/assembler.h> 12207a6cb0SLin Yongting#include <asm/unwind.h> 1375494230SNicolas Pitre 1475494230SNicolas Pitre .text 1575494230SNicolas Pitre 1675494230SNicolas Pitre/* 1775494230SNicolas Pitre * Prototype: void *memmove(void *dest, const void *src, size_t n); 1875494230SNicolas Pitre * 1975494230SNicolas Pitre * Note: 2075494230SNicolas Pitre * 2175494230SNicolas Pitre * If the memory regions don't overlap, we simply branch to memcpy which is 2275494230SNicolas Pitre * normally a bit faster. Otherwise the copy is done going downwards. This 2375494230SNicolas Pitre * is a transposition of the code from copy_template.S but with the copy 2475494230SNicolas Pitre * occurring in the opposite direction. 2575494230SNicolas Pitre */ 2675494230SNicolas Pitre 27d6d51a96SLinus WalleijENTRY(__memmove) 28735e8d93SFangrui SongWEAK(memmove) 29207a6cb0SLin Yongting UNWIND( .fnstart ) 3075494230SNicolas Pitre 3175494230SNicolas Pitre subs ip, r0, r1 3275494230SNicolas Pitre cmphi r2, ip 33d6d51a96SLinus Walleij bls __memcpy 34207a6cb0SLin Yongting UNWIND( .fnend ) 35207a6cb0SLin Yongting 36207a6cb0SLin Yongting UNWIND( .fnstart ) 37*ccb81601SArd Biesheuvel UNWIND( .save {r0, r4, fpreg, lr} ) 38*ccb81601SArd Biesheuvel stmfd sp!, {r0, r4, UNWIND(fpreg,) lr} 39*ccb81601SArd Biesheuvel UNWIND( .setfp fpreg, sp ) 40*ccb81601SArd Biesheuvel UNWIND( mov fpreg, sp ) 4175494230SNicolas Pitre add r1, r1, r2 4275494230SNicolas Pitre add r0, r0, r2 4375494230SNicolas Pitre subs r2, r2, #4 4475494230SNicolas Pitre blt 8f 4575494230SNicolas Pitre ands ip, r0, #3 4675494230SNicolas Pitre PLD( pld [r1, #-4] ) 4775494230SNicolas Pitre bne 9f 4875494230SNicolas Pitre ands ip, r1, #3 4975494230SNicolas Pitre bne 10f 5075494230SNicolas Pitre 5175494230SNicolas Pitre1: subs r2, r2, #(28) 52*ccb81601SArd Biesheuvel stmfd sp!, {r5, r6, r8, r9} 5375494230SNicolas Pitre blt 5f 5475494230SNicolas Pitre 552239aff6SNicolas Pitre CALGN( ands ip, r0, #31 ) 56e44fc388SStefan Agner CALGN( sbcsne r4, ip, r2 ) @ C is always set here 5775494230SNicolas Pitre CALGN( bcs 2f ) 5875494230SNicolas Pitre CALGN( adr r4, 6f ) 5975494230SNicolas Pitre CALGN( subs r2, r2, ip ) @ C is set here 604c4925c1SNicolas Pitre CALGN( rsb ip, ip, #32 ) 6175494230SNicolas Pitre CALGN( add pc, r4, ip ) 6275494230SNicolas Pitre 6375494230SNicolas Pitre PLD( pld [r1, #-4] ) 6475494230SNicolas Pitre2: PLD( subs r2, r2, #96 ) 6575494230SNicolas Pitre PLD( pld [r1, #-32] ) 6675494230SNicolas Pitre PLD( blt 4f ) 6775494230SNicolas Pitre PLD( pld [r1, #-64] ) 6875494230SNicolas Pitre PLD( pld [r1, #-96] ) 6975494230SNicolas Pitre 7075494230SNicolas Pitre3: PLD( pld [r1, #-128] ) 71*ccb81601SArd Biesheuvel4: ldmdb r1!, {r3, r4, r5, r6, r8, r9, ip, lr} 7275494230SNicolas Pitre subs r2, r2, #32 73*ccb81601SArd Biesheuvel stmdb r0!, {r3, r4, r5, r6, r8, r9, ip, lr} 7475494230SNicolas Pitre bge 3b 7575494230SNicolas Pitre PLD( cmn r2, #96 ) 7675494230SNicolas Pitre PLD( bge 4b ) 7775494230SNicolas Pitre 7875494230SNicolas Pitre5: ands ip, r2, #28 7975494230SNicolas Pitre rsb ip, ip, #32 8075494230SNicolas Pitre addne pc, pc, ip @ C is always clear here 8175494230SNicolas Pitre b 7f 82fd522a8dSCatalin Marinas6: W(nop) 838b592783SCatalin Marinas W(ldr) r3, [r1, #-4]! 848b592783SCatalin Marinas W(ldr) r4, [r1, #-4]! 858b592783SCatalin Marinas W(ldr) r5, [r1, #-4]! 868b592783SCatalin Marinas W(ldr) r6, [r1, #-4]! 878b592783SCatalin Marinas W(ldr) r8, [r1, #-4]! 88*ccb81601SArd Biesheuvel W(ldr) r9, [r1, #-4]! 898b592783SCatalin Marinas W(ldr) lr, [r1, #-4]! 9075494230SNicolas Pitre 9175494230SNicolas Pitre add pc, pc, ip 9275494230SNicolas Pitre nop 93fd522a8dSCatalin Marinas W(nop) 948b592783SCatalin Marinas W(str) r3, [r0, #-4]! 958b592783SCatalin Marinas W(str) r4, [r0, #-4]! 968b592783SCatalin Marinas W(str) r5, [r0, #-4]! 978b592783SCatalin Marinas W(str) r6, [r0, #-4]! 988b592783SCatalin Marinas W(str) r8, [r0, #-4]! 99*ccb81601SArd Biesheuvel W(str) r9, [r0, #-4]! 1008b592783SCatalin Marinas W(str) lr, [r0, #-4]! 10175494230SNicolas Pitre 10275494230SNicolas Pitre CALGN( bcs 2b ) 10375494230SNicolas Pitre 104*ccb81601SArd Biesheuvel7: ldmfd sp!, {r5, r6, r8, r9} 10575494230SNicolas Pitre 10675494230SNicolas Pitre8: movs r2, r2, lsl #31 107e44fc388SStefan Agner ldrbne r3, [r1, #-1]! 108e44fc388SStefan Agner ldrbcs r4, [r1, #-1]! 109e44fc388SStefan Agner ldrbcs ip, [r1, #-1] 110e44fc388SStefan Agner strbne r3, [r0, #-1]! 111e44fc388SStefan Agner strbcs r4, [r0, #-1]! 112e44fc388SStefan Agner strbcs ip, [r0, #-1] 113*ccb81601SArd Biesheuvel ldmfd sp!, {r0, r4, UNWIND(fpreg,) pc} 11475494230SNicolas Pitre 11575494230SNicolas Pitre9: cmp ip, #2 116e44fc388SStefan Agner ldrbgt r3, [r1, #-1]! 117e44fc388SStefan Agner ldrbge r4, [r1, #-1]! 11875494230SNicolas Pitre ldrb lr, [r1, #-1]! 119e44fc388SStefan Agner strbgt r3, [r0, #-1]! 120e44fc388SStefan Agner strbge r4, [r0, #-1]! 12175494230SNicolas Pitre subs r2, r2, ip 12275494230SNicolas Pitre strb lr, [r0, #-1]! 12375494230SNicolas Pitre blt 8b 12475494230SNicolas Pitre ands ip, r1, #3 12575494230SNicolas Pitre beq 1b 12675494230SNicolas Pitre 12775494230SNicolas Pitre10: bic r1, r1, #3 12875494230SNicolas Pitre cmp ip, #2 12975494230SNicolas Pitre ldr r3, [r1, #0] 13075494230SNicolas Pitre beq 17f 13175494230SNicolas Pitre blt 18f 13275494230SNicolas Pitre 13375494230SNicolas Pitre 13475494230SNicolas Pitre .macro backward_copy_shift push pull 13575494230SNicolas Pitre 13675494230SNicolas Pitre subs r2, r2, #28 13775494230SNicolas Pitre blt 14f 13875494230SNicolas Pitre 1392239aff6SNicolas Pitre CALGN( ands ip, r0, #31 ) 140e44fc388SStefan Agner CALGN( sbcsne r4, ip, r2 ) @ C is always set here 14175494230SNicolas Pitre CALGN( subcc r2, r2, ip ) 14275494230SNicolas Pitre CALGN( bcc 15f ) 14375494230SNicolas Pitre 144*ccb81601SArd Biesheuvel11: stmfd sp!, {r5, r6, r8 - r10} 14575494230SNicolas Pitre 14675494230SNicolas Pitre PLD( pld [r1, #-4] ) 14775494230SNicolas Pitre PLD( subs r2, r2, #96 ) 14875494230SNicolas Pitre PLD( pld [r1, #-32] ) 14975494230SNicolas Pitre PLD( blt 13f ) 15075494230SNicolas Pitre PLD( pld [r1, #-64] ) 15175494230SNicolas Pitre PLD( pld [r1, #-96] ) 15275494230SNicolas Pitre 15375494230SNicolas Pitre12: PLD( pld [r1, #-128] ) 154*ccb81601SArd Biesheuvel13: ldmdb r1!, {r8, r9, r10, ip} 155d98b90eaSVictor Kamensky mov lr, r3, lspush #\push 15675494230SNicolas Pitre subs r2, r2, #32 15775494230SNicolas Pitre ldmdb r1!, {r3, r4, r5, r6} 158d98b90eaSVictor Kamensky orr lr, lr, ip, lspull #\pull 159d98b90eaSVictor Kamensky mov ip, ip, lspush #\push 160*ccb81601SArd Biesheuvel orr ip, ip, r10, lspull #\pull 161*ccb81601SArd Biesheuvel mov r10, r10, lspush #\push 162*ccb81601SArd Biesheuvel orr r10, r10, r9, lspull #\pull 163d98b90eaSVictor Kamensky mov r9, r9, lspush #\push 164d98b90eaSVictor Kamensky orr r9, r9, r8, lspull #\pull 165d98b90eaSVictor Kamensky mov r8, r8, lspush #\push 166*ccb81601SArd Biesheuvel orr r8, r8, r6, lspull #\pull 167d98b90eaSVictor Kamensky mov r6, r6, lspush #\push 168d98b90eaSVictor Kamensky orr r6, r6, r5, lspull #\pull 169d98b90eaSVictor Kamensky mov r5, r5, lspush #\push 170d98b90eaSVictor Kamensky orr r5, r5, r4, lspull #\pull 171d98b90eaSVictor Kamensky mov r4, r4, lspush #\push 172d98b90eaSVictor Kamensky orr r4, r4, r3, lspull #\pull 173*ccb81601SArd Biesheuvel stmdb r0!, {r4 - r6, r8 - r10, ip, lr} 17475494230SNicolas Pitre bge 12b 17575494230SNicolas Pitre PLD( cmn r2, #96 ) 17675494230SNicolas Pitre PLD( bge 13b ) 17775494230SNicolas Pitre 178*ccb81601SArd Biesheuvel ldmfd sp!, {r5, r6, r8 - r10} 17975494230SNicolas Pitre 18075494230SNicolas Pitre14: ands ip, r2, #28 18175494230SNicolas Pitre beq 16f 18275494230SNicolas Pitre 183d98b90eaSVictor Kamensky15: mov lr, r3, lspush #\push 18475494230SNicolas Pitre ldr r3, [r1, #-4]! 18575494230SNicolas Pitre subs ip, ip, #4 186d98b90eaSVictor Kamensky orr lr, lr, r3, lspull #\pull 18775494230SNicolas Pitre str lr, [r0, #-4]! 18875494230SNicolas Pitre bgt 15b 18975494230SNicolas Pitre CALGN( cmp r2, #0 ) 19075494230SNicolas Pitre CALGN( bge 11b ) 19175494230SNicolas Pitre 19275494230SNicolas Pitre16: add r1, r1, #(\pull / 8) 19375494230SNicolas Pitre b 8b 19475494230SNicolas Pitre 19575494230SNicolas Pitre .endm 19675494230SNicolas Pitre 19775494230SNicolas Pitre 19875494230SNicolas Pitre backward_copy_shift push=8 pull=24 19975494230SNicolas Pitre 20075494230SNicolas Pitre17: backward_copy_shift push=16 pull=16 20175494230SNicolas Pitre 20275494230SNicolas Pitre18: backward_copy_shift push=24 pull=8 20375494230SNicolas Pitre 204*ccb81601SArd Biesheuvel UNWIND( .fnend ) 20593ed3970SCatalin MarinasENDPROC(memmove) 206d6d51a96SLinus WalleijENDPROC(__memmove) 207