1d8834a13SMatthias Weisser/* 2d8834a13SMatthias Weisser * linux/arch/arm/lib/memcpy.S 3d8834a13SMatthias Weisser * 4d8834a13SMatthias Weisser * Author: Nicolas Pitre 5d8834a13SMatthias Weisser * Created: Sep 28, 2005 6d8834a13SMatthias Weisser * Copyright: MontaVista Software, Inc. 7d8834a13SMatthias Weisser * 8d8834a13SMatthias Weisser * This program is free software; you can redistribute it and/or modify 9d8834a13SMatthias Weisser * it under the terms of the GNU General Public License version 2 as 10d8834a13SMatthias Weisser * published by the Free Software Foundation. 11d8834a13SMatthias Weisser */ 12d8834a13SMatthias Weisser 1375d7a0d7SStefan Agner#include <linux/linkage.h> 14d8834a13SMatthias Weisser#include <asm/assembler.h> 15d8834a13SMatthias Weisser 16d8834a13SMatthias Weisser#define LDR1W_SHIFT 0 17d8834a13SMatthias Weisser#define STR1W_SHIFT 0 18d8834a13SMatthias Weisser 19d8834a13SMatthias Weisser .macro ldr1w ptr reg abort 20d8834a13SMatthias Weisser W(ldr) \reg, [\ptr], #4 21d8834a13SMatthias Weisser .endm 22d8834a13SMatthias Weisser 23d8834a13SMatthias Weisser .macro ldr4w ptr reg1 reg2 reg3 reg4 abort 24d8834a13SMatthias Weisser ldmia \ptr!, {\reg1, \reg2, \reg3, \reg4} 25d8834a13SMatthias Weisser .endm 26d8834a13SMatthias Weisser 27d8834a13SMatthias Weisser .macro ldr8w ptr reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 abort 28d8834a13SMatthias Weisser ldmia \ptr!, {\reg1, \reg2, \reg3, \reg4, \reg5, \reg6, \reg7, \reg8} 29d8834a13SMatthias Weisser .endm 30d8834a13SMatthias Weisser 31d8834a13SMatthias Weisser .macro ldr1b ptr reg cond=al abort 3275d7a0d7SStefan Agner ldrb\cond\() \reg, [\ptr], #1 33d8834a13SMatthias Weisser .endm 34d8834a13SMatthias Weisser 35d8834a13SMatthias Weisser .macro str1w ptr reg abort 36d8834a13SMatthias Weisser W(str) \reg, [\ptr], #4 37d8834a13SMatthias Weisser .endm 38d8834a13SMatthias Weisser 39d8834a13SMatthias Weisser .macro str8w ptr reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 abort 40d8834a13SMatthias Weisser stmia \ptr!, {\reg1, \reg2, \reg3, \reg4, \reg5, \reg6, \reg7, \reg8} 41d8834a13SMatthias Weisser .endm 42d8834a13SMatthias Weisser 43d8834a13SMatthias Weisser .macro str1b ptr reg cond=al abort 4475d7a0d7SStefan Agner strb\cond\() \reg, [\ptr], #1 45d8834a13SMatthias Weisser .endm 46d8834a13SMatthias Weisser 47d8834a13SMatthias Weisser .macro enter reg1 reg2 48d8834a13SMatthias Weisser stmdb sp!, {r0, \reg1, \reg2} 49d8834a13SMatthias Weisser .endm 50d8834a13SMatthias Weisser 51d8834a13SMatthias Weisser .macro exit reg1 reg2 52d8834a13SMatthias Weisser ldmfd sp!, {r0, \reg1, \reg2} 53d8834a13SMatthias Weisser .endm 54d8834a13SMatthias Weisser 55d8834a13SMatthias Weisser .text 56d8834a13SMatthias Weisser 57d8834a13SMatthias Weisser/* Prototype: void *memcpy(void *dest, const void *src, size_t n); */ 5875d7a0d7SStefan Agner .syntax unified 59*3a649407STom Rini#if CONFIG_IS_ENABLED(SYS_THUMB_BUILD) && !defined(MEMCPY_NO_THUMB_BUILD) 6075d7a0d7SStefan Agner .thumb 6175d7a0d7SStefan Agner .thumb_func 6275d7a0d7SStefan Agner#endif 6375d7a0d7SStefan AgnerENTRY(memcpy) 6434fe8281SMatthias Weisser cmp r0, r1 6534fe8281SMatthias Weisser moveq pc, lr 6634fe8281SMatthias Weisser 67d8834a13SMatthias Weisser enter r4, lr 68d8834a13SMatthias Weisser 69d8834a13SMatthias Weisser subs r2, r2, #4 70d8834a13SMatthias Weisser blt 8f 71d8834a13SMatthias Weisser ands ip, r0, #3 72d8834a13SMatthias Weisser PLD( pld [r1, #0] ) 73d8834a13SMatthias Weisser bne 9f 74d8834a13SMatthias Weisser ands ip, r1, #3 75d8834a13SMatthias Weisser bne 10f 76d8834a13SMatthias Weisser 77d8834a13SMatthias Weisser1: subs r2, r2, #(28) 78d8834a13SMatthias Weisser stmfd sp!, {r5 - r8} 79d8834a13SMatthias Weisser blt 5f 80d8834a13SMatthias Weisser 81d8834a13SMatthias Weisser CALGN( ands ip, r0, #31 ) 82d8834a13SMatthias Weisser CALGN( rsb r3, ip, #32 ) 8375d7a0d7SStefan Agner CALGN( sbcsne r4, r3, r2 ) @ C is always set here 84d8834a13SMatthias Weisser CALGN( bcs 2f ) 85d8834a13SMatthias Weisser CALGN( adr r4, 6f ) 86d8834a13SMatthias Weisser CALGN( subs r2, r2, r3 ) @ C gets set 87d8834a13SMatthias Weisser CALGN( add pc, r4, ip ) 88d8834a13SMatthias Weisser 89d8834a13SMatthias Weisser PLD( pld [r1, #0] ) 90d8834a13SMatthias Weisser2: PLD( subs r2, r2, #96 ) 91d8834a13SMatthias Weisser PLD( pld [r1, #28] ) 92d8834a13SMatthias Weisser PLD( blt 4f ) 93d8834a13SMatthias Weisser PLD( pld [r1, #60] ) 94d8834a13SMatthias Weisser PLD( pld [r1, #92] ) 95d8834a13SMatthias Weisser 96d8834a13SMatthias Weisser3: PLD( pld [r1, #124] ) 97d8834a13SMatthias Weisser4: ldr8w r1, r3, r4, r5, r6, r7, r8, ip, lr, abort=20f 98d8834a13SMatthias Weisser subs r2, r2, #32 99d8834a13SMatthias Weisser str8w r0, r3, r4, r5, r6, r7, r8, ip, lr, abort=20f 100d8834a13SMatthias Weisser bge 3b 101d8834a13SMatthias Weisser PLD( cmn r2, #96 ) 102d8834a13SMatthias Weisser PLD( bge 4b ) 103d8834a13SMatthias Weisser 104d8834a13SMatthias Weisser5: ands ip, r2, #28 105d8834a13SMatthias Weisser rsb ip, ip, #32 106d8834a13SMatthias Weisser#if LDR1W_SHIFT > 0 107d8834a13SMatthias Weisser lsl ip, ip, #LDR1W_SHIFT 108d8834a13SMatthias Weisser#endif 109d8834a13SMatthias Weisser addne pc, pc, ip @ C is always clear here 110d8834a13SMatthias Weisser b 7f 111d8834a13SMatthias Weisser6: 112d8834a13SMatthias Weisser .rept (1 << LDR1W_SHIFT) 113d8834a13SMatthias Weisser W(nop) 114d8834a13SMatthias Weisser .endr 115d8834a13SMatthias Weisser ldr1w r1, r3, abort=20f 116d8834a13SMatthias Weisser ldr1w r1, r4, abort=20f 117d8834a13SMatthias Weisser ldr1w r1, r5, abort=20f 118d8834a13SMatthias Weisser ldr1w r1, r6, abort=20f 119d8834a13SMatthias Weisser ldr1w r1, r7, abort=20f 120d8834a13SMatthias Weisser ldr1w r1, r8, abort=20f 121d8834a13SMatthias Weisser ldr1w r1, lr, abort=20f 122d8834a13SMatthias Weisser 123d8834a13SMatthias Weisser#if LDR1W_SHIFT < STR1W_SHIFT 124d8834a13SMatthias Weisser lsl ip, ip, #STR1W_SHIFT - LDR1W_SHIFT 125d8834a13SMatthias Weisser#elif LDR1W_SHIFT > STR1W_SHIFT 126d8834a13SMatthias Weisser lsr ip, ip, #LDR1W_SHIFT - STR1W_SHIFT 127d8834a13SMatthias Weisser#endif 128d8834a13SMatthias Weisser add pc, pc, ip 129d8834a13SMatthias Weisser nop 130d8834a13SMatthias Weisser .rept (1 << STR1W_SHIFT) 131d8834a13SMatthias Weisser W(nop) 132d8834a13SMatthias Weisser .endr 133d8834a13SMatthias Weisser str1w r0, r3, abort=20f 134d8834a13SMatthias Weisser str1w r0, r4, abort=20f 135d8834a13SMatthias Weisser str1w r0, r5, abort=20f 136d8834a13SMatthias Weisser str1w r0, r6, abort=20f 137d8834a13SMatthias Weisser str1w r0, r7, abort=20f 138d8834a13SMatthias Weisser str1w r0, r8, abort=20f 139d8834a13SMatthias Weisser str1w r0, lr, abort=20f 140d8834a13SMatthias Weisser 141d8834a13SMatthias Weisser CALGN( bcs 2b ) 142d8834a13SMatthias Weisser 143d8834a13SMatthias Weisser7: ldmfd sp!, {r5 - r8} 144d8834a13SMatthias Weisser 145d8834a13SMatthias Weisser8: movs r2, r2, lsl #31 146d8834a13SMatthias Weisser ldr1b r1, r3, ne, abort=21f 147d8834a13SMatthias Weisser ldr1b r1, r4, cs, abort=21f 148d8834a13SMatthias Weisser ldr1b r1, ip, cs, abort=21f 149d8834a13SMatthias Weisser str1b r0, r3, ne, abort=21f 150d8834a13SMatthias Weisser str1b r0, r4, cs, abort=21f 151d8834a13SMatthias Weisser str1b r0, ip, cs, abort=21f 152d8834a13SMatthias Weisser 153d8834a13SMatthias Weisser exit r4, pc 154d8834a13SMatthias Weisser 155d8834a13SMatthias Weisser9: rsb ip, ip, #4 156d8834a13SMatthias Weisser cmp ip, #2 157d8834a13SMatthias Weisser ldr1b r1, r3, gt, abort=21f 158d8834a13SMatthias Weisser ldr1b r1, r4, ge, abort=21f 159d8834a13SMatthias Weisser ldr1b r1, lr, abort=21f 160d8834a13SMatthias Weisser str1b r0, r3, gt, abort=21f 161d8834a13SMatthias Weisser str1b r0, r4, ge, abort=21f 162d8834a13SMatthias Weisser subs r2, r2, ip 163d8834a13SMatthias Weisser str1b r0, lr, abort=21f 164d8834a13SMatthias Weisser blt 8b 165d8834a13SMatthias Weisser ands ip, r1, #3 166d8834a13SMatthias Weisser beq 1b 167d8834a13SMatthias Weisser 168d8834a13SMatthias Weisser10: bic r1, r1, #3 169d8834a13SMatthias Weisser cmp ip, #2 170d8834a13SMatthias Weisser ldr1w r1, lr, abort=21f 171d8834a13SMatthias Weisser beq 17f 172d8834a13SMatthias Weisser bgt 18f 173d8834a13SMatthias Weisser 174d8834a13SMatthias Weisser 175d8834a13SMatthias Weisser .macro forward_copy_shift pull push 176d8834a13SMatthias Weisser 177d8834a13SMatthias Weisser subs r2, r2, #28 178d8834a13SMatthias Weisser blt 14f 179d8834a13SMatthias Weisser 180d8834a13SMatthias Weisser CALGN( ands ip, r0, #31 ) 181d8834a13SMatthias Weisser CALGN( rsb ip, ip, #32 ) 18275d7a0d7SStefan Agner CALGN( sbcsne r4, ip, r2 ) @ C is always set here 183d8834a13SMatthias Weisser CALGN( subcc r2, r2, ip ) 184d8834a13SMatthias Weisser CALGN( bcc 15f ) 185d8834a13SMatthias Weisser 186d8834a13SMatthias Weisser11: stmfd sp!, {r5 - r9} 187d8834a13SMatthias Weisser 188d8834a13SMatthias Weisser PLD( pld [r1, #0] ) 189d8834a13SMatthias Weisser PLD( subs r2, r2, #96 ) 190d8834a13SMatthias Weisser PLD( pld [r1, #28] ) 191d8834a13SMatthias Weisser PLD( blt 13f ) 192d8834a13SMatthias Weisser PLD( pld [r1, #60] ) 193d8834a13SMatthias Weisser PLD( pld [r1, #92] ) 194d8834a13SMatthias Weisser 195d8834a13SMatthias Weisser12: PLD( pld [r1, #124] ) 196d8834a13SMatthias Weisser13: ldr4w r1, r4, r5, r6, r7, abort=19f 19775d7a0d7SStefan Agner mov r3, lr, lspull #\pull 198d8834a13SMatthias Weisser subs r2, r2, #32 199d8834a13SMatthias Weisser ldr4w r1, r8, r9, ip, lr, abort=19f 20075d7a0d7SStefan Agner orr r3, r3, r4, lspush #\push 20175d7a0d7SStefan Agner mov r4, r4, lspull #\pull 20275d7a0d7SStefan Agner orr r4, r4, r5, lspush #\push 20375d7a0d7SStefan Agner mov r5, r5, lspull #\pull 20475d7a0d7SStefan Agner orr r5, r5, r6, lspush #\push 20575d7a0d7SStefan Agner mov r6, r6, lspull #\pull 20675d7a0d7SStefan Agner orr r6, r6, r7, lspush #\push 20775d7a0d7SStefan Agner mov r7, r7, lspull #\pull 20875d7a0d7SStefan Agner orr r7, r7, r8, lspush #\push 20975d7a0d7SStefan Agner mov r8, r8, lspull #\pull 21075d7a0d7SStefan Agner orr r8, r8, r9, lspush #\push 21175d7a0d7SStefan Agner mov r9, r9, lspull #\pull 21275d7a0d7SStefan Agner orr r9, r9, ip, lspush #\push 21375d7a0d7SStefan Agner mov ip, ip, lspull #\pull 21475d7a0d7SStefan Agner orr ip, ip, lr, lspush #\push 215d8834a13SMatthias Weisser str8w r0, r3, r4, r5, r6, r7, r8, r9, ip, , abort=19f 216d8834a13SMatthias Weisser bge 12b 217d8834a13SMatthias Weisser PLD( cmn r2, #96 ) 218d8834a13SMatthias Weisser PLD( bge 13b ) 219d8834a13SMatthias Weisser 220d8834a13SMatthias Weisser ldmfd sp!, {r5 - r9} 221d8834a13SMatthias Weisser 222d8834a13SMatthias Weisser14: ands ip, r2, #28 223d8834a13SMatthias Weisser beq 16f 224d8834a13SMatthias Weisser 22575d7a0d7SStefan Agner15: mov r3, lr, lspull #\pull 226d8834a13SMatthias Weisser ldr1w r1, lr, abort=21f 227d8834a13SMatthias Weisser subs ip, ip, #4 22875d7a0d7SStefan Agner orr r3, r3, lr, lspush #\push 229d8834a13SMatthias Weisser str1w r0, r3, abort=21f 230d8834a13SMatthias Weisser bgt 15b 231d8834a13SMatthias Weisser CALGN( cmp r2, #0 ) 232d8834a13SMatthias Weisser CALGN( bge 11b ) 233d8834a13SMatthias Weisser 234d8834a13SMatthias Weisser16: sub r1, r1, #(\push / 8) 235d8834a13SMatthias Weisser b 8b 236d8834a13SMatthias Weisser 237d8834a13SMatthias Weisser .endm 238d8834a13SMatthias Weisser 239d8834a13SMatthias Weisser 240d8834a13SMatthias Weisser forward_copy_shift pull=8 push=24 241d8834a13SMatthias Weisser 242d8834a13SMatthias Weisser17: forward_copy_shift pull=16 push=16 243d8834a13SMatthias Weisser 244d8834a13SMatthias Weisser18: forward_copy_shift pull=24 push=8 24575d7a0d7SStefan Agner 24675d7a0d7SStefan Agner 24775d7a0d7SStefan Agner/* 24875d7a0d7SStefan Agner * Abort preamble and completion macros. 24975d7a0d7SStefan Agner * If a fixup handler is required then those macros must surround it. 25075d7a0d7SStefan Agner * It is assumed that the fixup code will handle the private part of 25175d7a0d7SStefan Agner * the exit macro. 25275d7a0d7SStefan Agner */ 25375d7a0d7SStefan Agner 25475d7a0d7SStefan Agner .macro copy_abort_preamble 25575d7a0d7SStefan Agner19: ldmfd sp!, {r5 - r9} 25675d7a0d7SStefan Agner b 21f 25775d7a0d7SStefan Agner20: ldmfd sp!, {r5 - r8} 25875d7a0d7SStefan Agner21: 25975d7a0d7SStefan Agner .endm 26075d7a0d7SStefan Agner 26175d7a0d7SStefan Agner .macro copy_abort_end 26275d7a0d7SStefan Agner ldmfd sp!, {r4, pc} 26375d7a0d7SStefan Agner .endm 26475d7a0d7SStefan Agner 26575d7a0d7SStefan AgnerENDPROC(memcpy) 266