1*0a6a1f1dSLionel Sambuc/* $NetBSD: memmove.S,v 1.9 2015/03/26 13:34:51 justin Exp $ */ 2b6cbf720SGianluca Guida 3b6cbf720SGianluca Guida/*- 4b6cbf720SGianluca Guida * Copyright (c) 1997 The NetBSD Foundation, Inc. 5b6cbf720SGianluca Guida * All rights reserved. 6b6cbf720SGianluca Guida * 7b6cbf720SGianluca Guida * This code is derived from software contributed to The NetBSD Foundation 8b6cbf720SGianluca Guida * by Neil A. Carson and Mark Brinicombe 9b6cbf720SGianluca Guida * 10b6cbf720SGianluca Guida * Redistribution and use in source and binary forms, with or without 11b6cbf720SGianluca Guida * modification, are permitted provided that the following conditions 12b6cbf720SGianluca Guida * are met: 13b6cbf720SGianluca Guida * 1. Redistributions of source code must retain the above copyright 14b6cbf720SGianluca Guida * notice, this list of conditions and the following disclaimer. 15b6cbf720SGianluca Guida * 2. Redistributions in binary form must reproduce the above copyright 16b6cbf720SGianluca Guida * notice, this list of conditions and the following disclaimer in the 17b6cbf720SGianluca Guida * documentation and/or other materials provided with the distribution. 18b6cbf720SGianluca Guida * 19b6cbf720SGianluca Guida * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20b6cbf720SGianluca Guida * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21b6cbf720SGianluca Guida * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22b6cbf720SGianluca Guida * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23b6cbf720SGianluca Guida * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24b6cbf720SGianluca Guida * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25b6cbf720SGianluca Guida * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26b6cbf720SGianluca Guida * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27b6cbf720SGianluca Guida * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28b6cbf720SGianluca Guida * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29b6cbf720SGianluca Guida * POSSIBILITY OF SUCH DAMAGE. 30b6cbf720SGianluca Guida */ 31b6cbf720SGianluca Guida 32b6cbf720SGianluca Guida#include <machine/asm.h> 33b6cbf720SGianluca Guida 34b6cbf720SGianluca Guida#ifndef _BCOPY 35b6cbf720SGianluca Guida/* LINTSTUB: Func: void *memmove(void *, const void *, size_t) */ 36b6cbf720SGianluca GuidaENTRY(memmove) 37b6cbf720SGianluca Guida#else 38b6cbf720SGianluca Guida/* bcopy = memcpy/memmove with arguments reversed. */ 39b6cbf720SGianluca Guida/* LINTSTUB: Func: void bcopy(void *, void *, size_t) */ 40b6cbf720SGianluca GuidaENTRY(bcopy) 41b6cbf720SGianluca Guida /* switch the source and destination registers */ 42b6cbf720SGianluca Guida eor r0, r1, r0 43b6cbf720SGianluca Guida eor r1, r0, r1 44b6cbf720SGianluca Guida eor r0, r1, r0 45b6cbf720SGianluca Guida#endif 46b6cbf720SGianluca Guida /* Do the buffers overlap? */ 47b6cbf720SGianluca Guida cmp r0, r1 48b6cbf720SGianluca Guida RETc(eq) /* Bail now if src/dst are the same */ 49b6cbf720SGianluca Guida subhs r3, r0, r1 /* if (dst > src) r3 = dst - src */ 50b6cbf720SGianluca Guida sublo r3, r1, r0 /* if (src > dst) r3 = src - dst */ 51b6cbf720SGianluca Guida cmp r3, r2 /* if (r3 >= len) we have an overlap */ 5284d9c625SLionel Sambuc bhs PLT_SYM(_C_LABEL(memcpy)) 53b6cbf720SGianluca Guida 54b6cbf720SGianluca Guida /* Determine copy direction */ 55b6cbf720SGianluca Guida cmp r1, r0 56b6cbf720SGianluca Guida bcc .Lmemmove_backwards 57b6cbf720SGianluca Guida 58b6cbf720SGianluca Guida moveq r0, #0 /* Quick abort for len=0 */ 59b6cbf720SGianluca Guida RETc(eq) 60b6cbf720SGianluca Guida 6184d9c625SLionel Sambuc push {r0, lr} /* memmove() returns dest addr */ 62b6cbf720SGianluca Guida subs r2, r2, #4 63b6cbf720SGianluca Guida blt .Lmemmove_fl4 /* less than 4 bytes */ 64b6cbf720SGianluca Guida ands r12, r0, #3 65b6cbf720SGianluca Guida bne .Lmemmove_fdestul /* oh unaligned destination addr */ 66b6cbf720SGianluca Guida ands r12, r1, #3 67b6cbf720SGianluca Guida bne .Lmemmove_fsrcul /* oh unaligned source addr */ 68b6cbf720SGianluca Guida 69b6cbf720SGianluca Guida.Lmemmove_ft8: 70b6cbf720SGianluca Guida /* We have aligned source and destination */ 71b6cbf720SGianluca Guida subs r2, r2, #8 72b6cbf720SGianluca Guida blt .Lmemmove_fl12 /* less than 12 bytes (4 from above) */ 73b6cbf720SGianluca Guida subs r2, r2, #0x14 74b6cbf720SGianluca Guida blt .Lmemmove_fl32 /* less than 32 bytes (12 from above) */ 7584d9c625SLionel Sambuc push {r4} /* borrow r4 */ 76b6cbf720SGianluca Guida 77b6cbf720SGianluca Guida /* blat 32 bytes at a time */ 78b6cbf720SGianluca Guida /* XXX for really big copies perhaps we should use more registers */ 79b6cbf720SGianluca Guida.Lmemmove_floop32: 80b6cbf720SGianluca Guida ldmia r1!, {r3, r4, r12, lr} 81b6cbf720SGianluca Guida stmia r0!, {r3, r4, r12, lr} 82b6cbf720SGianluca Guida ldmia r1!, {r3, r4, r12, lr} 83b6cbf720SGianluca Guida stmia r0!, {r3, r4, r12, lr} 84b6cbf720SGianluca Guida subs r2, r2, #0x20 85b6cbf720SGianluca Guida bge .Lmemmove_floop32 86b6cbf720SGianluca Guida 87b6cbf720SGianluca Guida cmn r2, #0x10 8884d9c625SLionel Sambuc ldmiage r1!, {r3, r4, r12, lr} /* blat a remaining 16 bytes */ 8984d9c625SLionel Sambuc stmiage r0!, {r3, r4, r12, lr} 90b6cbf720SGianluca Guida subge r2, r2, #0x10 9184d9c625SLionel Sambuc pop {r4} /* return r4 */ 92b6cbf720SGianluca Guida 93b6cbf720SGianluca Guida.Lmemmove_fl32: 94b6cbf720SGianluca Guida adds r2, r2, #0x14 95b6cbf720SGianluca Guida 96b6cbf720SGianluca Guida /* blat 12 bytes at a time */ 97b6cbf720SGianluca Guida.Lmemmove_floop12: 9884d9c625SLionel Sambuc ldmiage r1!, {r3, r12, lr} 9984d9c625SLionel Sambuc stmiage r0!, {r3, r12, lr} 10084d9c625SLionel Sambuc subsge r2, r2, #0x0c 101b6cbf720SGianluca Guida bge .Lmemmove_floop12 102b6cbf720SGianluca Guida 103b6cbf720SGianluca Guida.Lmemmove_fl12: 104b6cbf720SGianluca Guida adds r2, r2, #8 105b6cbf720SGianluca Guida blt .Lmemmove_fl4 106b6cbf720SGianluca Guida 107b6cbf720SGianluca Guida subs r2, r2, #4 108b6cbf720SGianluca Guida ldrlt r3, [r1], #4 109b6cbf720SGianluca Guida strlt r3, [r0], #4 11084d9c625SLionel Sambuc ldmiage r1!, {r3, r12} 11184d9c625SLionel Sambuc stmiage r0!, {r3, r12} 112b6cbf720SGianluca Guida subge r2, r2, #4 113b6cbf720SGianluca Guida 114b6cbf720SGianluca Guida.Lmemmove_fl4: 115b6cbf720SGianluca Guida /* less than 4 bytes to go */ 116b6cbf720SGianluca Guida adds r2, r2, #4 11784d9c625SLionel Sambuc popeq {r0, pc} /* done */ 118b6cbf720SGianluca Guida 119b6cbf720SGianluca Guida /* copy the crud byte at a time */ 120b6cbf720SGianluca Guida cmp r2, #2 121b6cbf720SGianluca Guida ldrb r3, [r1], #1 122b6cbf720SGianluca Guida strb r3, [r0], #1 12384d9c625SLionel Sambuc ldrbge r3, [r1], #1 12484d9c625SLionel Sambuc strbge r3, [r0], #1 12584d9c625SLionel Sambuc ldrbgt r3, [r1], #1 12684d9c625SLionel Sambuc strbgt r3, [r0], #1 12784d9c625SLionel Sambuc pop {r0, pc} 128b6cbf720SGianluca Guida 129b6cbf720SGianluca Guida /* erg - unaligned destination */ 130b6cbf720SGianluca Guida.Lmemmove_fdestul: 131b6cbf720SGianluca Guida rsb r12, r12, #4 132b6cbf720SGianluca Guida cmp r12, #2 133b6cbf720SGianluca Guida 134b6cbf720SGianluca Guida /* align destination with byte copies */ 135b6cbf720SGianluca Guida ldrb r3, [r1], #1 136b6cbf720SGianluca Guida strb r3, [r0], #1 13784d9c625SLionel Sambuc ldrbge r3, [r1], #1 13884d9c625SLionel Sambuc strbge r3, [r0], #1 13984d9c625SLionel Sambuc ldrbgt r3, [r1], #1 14084d9c625SLionel Sambuc strbgt r3, [r0], #1 141b6cbf720SGianluca Guida subs r2, r2, r12 142b6cbf720SGianluca Guida blt .Lmemmove_fl4 /* less the 4 bytes */ 143b6cbf720SGianluca Guida 144b6cbf720SGianluca Guida ands r12, r1, #3 145b6cbf720SGianluca Guida beq .Lmemmove_ft8 /* we have an aligned source */ 146b6cbf720SGianluca Guida 147b6cbf720SGianluca Guida /* erg - unaligned source */ 148b6cbf720SGianluca Guida /* This is where it gets nasty ... */ 149b6cbf720SGianluca Guida.Lmemmove_fsrcul: 150b6cbf720SGianluca Guida bic r1, r1, #3 151b6cbf720SGianluca Guida ldr lr, [r1], #4 152b6cbf720SGianluca Guida cmp r12, #2 153b6cbf720SGianluca Guida bgt .Lmemmove_fsrcul3 154b6cbf720SGianluca Guida beq .Lmemmove_fsrcul2 155b6cbf720SGianluca Guida cmp r2, #0x0c 156b6cbf720SGianluca Guida blt .Lmemmove_fsrcul1loop4 157b6cbf720SGianluca Guida sub r2, r2, #0x0c 15884d9c625SLionel Sambuc push {r4, r5} 159b6cbf720SGianluca Guida 160b6cbf720SGianluca Guida.Lmemmove_fsrcul1loop16: 161b6cbf720SGianluca Guida#ifdef __ARMEB__ 162b6cbf720SGianluca Guida mov r3, lr, lsl #8 163b6cbf720SGianluca Guida#else 164b6cbf720SGianluca Guida mov r3, lr, lsr #8 165b6cbf720SGianluca Guida#endif 166b6cbf720SGianluca Guida ldmia r1!, {r4, r5, r12, lr} 167b6cbf720SGianluca Guida#ifdef __ARMEB__ 168b6cbf720SGianluca Guida orr r3, r3, r4, lsr #24 169b6cbf720SGianluca Guida mov r4, r4, lsl #8 170b6cbf720SGianluca Guida orr r4, r4, r5, lsr #24 171b6cbf720SGianluca Guida mov r5, r5, lsl #8 172b6cbf720SGianluca Guida orr r5, r5, r12, lsr #24 173b6cbf720SGianluca Guida mov r12, r12, lsl #8 174b6cbf720SGianluca Guida orr r12, r12, lr, lsr #24 175b6cbf720SGianluca Guida#else 176b6cbf720SGianluca Guida orr r3, r3, r4, lsl #24 177b6cbf720SGianluca Guida mov r4, r4, lsr #8 178b6cbf720SGianluca Guida orr r4, r4, r5, lsl #24 179b6cbf720SGianluca Guida mov r5, r5, lsr #8 180b6cbf720SGianluca Guida orr r5, r5, r12, lsl #24 181b6cbf720SGianluca Guida mov r12, r12, lsr #8 182b6cbf720SGianluca Guida orr r12, r12, lr, lsl #24 183b6cbf720SGianluca Guida#endif 184b6cbf720SGianluca Guida stmia r0!, {r3-r5, r12} 185b6cbf720SGianluca Guida subs r2, r2, #0x10 186b6cbf720SGianluca Guida bge .Lmemmove_fsrcul1loop16 18784d9c625SLionel Sambuc pop {r4, r5} 188b6cbf720SGianluca Guida adds r2, r2, #0x0c 189b6cbf720SGianluca Guida blt .Lmemmove_fsrcul1l4 190b6cbf720SGianluca Guida 191b6cbf720SGianluca Guida.Lmemmove_fsrcul1loop4: 192b6cbf720SGianluca Guida#ifdef __ARMEB__ 193b6cbf720SGianluca Guida mov r12, lr, lsl #8 194b6cbf720SGianluca Guida#else 195b6cbf720SGianluca Guida mov r12, lr, lsr #8 196b6cbf720SGianluca Guida#endif 197b6cbf720SGianluca Guida ldr lr, [r1], #4 198b6cbf720SGianluca Guida#ifdef __ARMEB__ 199b6cbf720SGianluca Guida orr r12, r12, lr, lsr #24 200b6cbf720SGianluca Guida#else 201b6cbf720SGianluca Guida orr r12, r12, lr, lsl #24 202b6cbf720SGianluca Guida#endif 203b6cbf720SGianluca Guida str r12, [r0], #4 204b6cbf720SGianluca Guida subs r2, r2, #4 205b6cbf720SGianluca Guida bge .Lmemmove_fsrcul1loop4 206b6cbf720SGianluca Guida 207b6cbf720SGianluca Guida.Lmemmove_fsrcul1l4: 208b6cbf720SGianluca Guida sub r1, r1, #3 209b6cbf720SGianluca Guida b .Lmemmove_fl4 210b6cbf720SGianluca Guida 211b6cbf720SGianluca Guida.Lmemmove_fsrcul2: 212b6cbf720SGianluca Guida cmp r2, #0x0c 213b6cbf720SGianluca Guida blt .Lmemmove_fsrcul2loop4 214b6cbf720SGianluca Guida sub r2, r2, #0x0c 21584d9c625SLionel Sambuc push {r4, r5} 216b6cbf720SGianluca Guida 217b6cbf720SGianluca Guida.Lmemmove_fsrcul2loop16: 218b6cbf720SGianluca Guida#ifdef __ARMEB__ 219b6cbf720SGianluca Guida mov r3, lr, lsl #16 220b6cbf720SGianluca Guida#else 221b6cbf720SGianluca Guida mov r3, lr, lsr #16 222b6cbf720SGianluca Guida#endif 223b6cbf720SGianluca Guida ldmia r1!, {r4, r5, r12, lr} 224b6cbf720SGianluca Guida#ifdef __ARMEB__ 225b6cbf720SGianluca Guida orr r3, r3, r4, lsr #16 226b6cbf720SGianluca Guida mov r4, r4, lsl #16 227b6cbf720SGianluca Guida orr r4, r4, r5, lsr #16 228b6cbf720SGianluca Guida mov r5, r5, lsl #16 229b6cbf720SGianluca Guida orr r5, r5, r12, lsr #16 230b6cbf720SGianluca Guida mov r12, r12, lsl #16 231b6cbf720SGianluca Guida orr r12, r12, lr, lsr #16 232b6cbf720SGianluca Guida#else 233b6cbf720SGianluca Guida orr r3, r3, r4, lsl #16 234b6cbf720SGianluca Guida mov r4, r4, lsr #16 235b6cbf720SGianluca Guida orr r4, r4, r5, lsl #16 236b6cbf720SGianluca Guida mov r5, r5, lsr #16 237b6cbf720SGianluca Guida orr r5, r5, r12, lsl #16 238b6cbf720SGianluca Guida mov r12, r12, lsr #16 239b6cbf720SGianluca Guida orr r12, r12, lr, lsl #16 240b6cbf720SGianluca Guida#endif 241b6cbf720SGianluca Guida stmia r0!, {r3-r5, r12} 242b6cbf720SGianluca Guida subs r2, r2, #0x10 243b6cbf720SGianluca Guida bge .Lmemmove_fsrcul2loop16 24484d9c625SLionel Sambuc pop {r4, r5} 245b6cbf720SGianluca Guida adds r2, r2, #0x0c 246b6cbf720SGianluca Guida blt .Lmemmove_fsrcul2l4 247b6cbf720SGianluca Guida 248b6cbf720SGianluca Guida.Lmemmove_fsrcul2loop4: 249b6cbf720SGianluca Guida#ifdef __ARMEB__ 250b6cbf720SGianluca Guida mov r12, lr, lsl #16 251b6cbf720SGianluca Guida#else 252b6cbf720SGianluca Guida mov r12, lr, lsr #16 253b6cbf720SGianluca Guida#endif 254b6cbf720SGianluca Guida ldr lr, [r1], #4 255b6cbf720SGianluca Guida#ifdef __ARMEB__ 256b6cbf720SGianluca Guida orr r12, r12, lr, lsr #16 257b6cbf720SGianluca Guida#else 258b6cbf720SGianluca Guida orr r12, r12, lr, lsl #16 259b6cbf720SGianluca Guida#endif 260b6cbf720SGianluca Guida str r12, [r0], #4 261b6cbf720SGianluca Guida subs r2, r2, #4 262b6cbf720SGianluca Guida bge .Lmemmove_fsrcul2loop4 263b6cbf720SGianluca Guida 264b6cbf720SGianluca Guida.Lmemmove_fsrcul2l4: 265b6cbf720SGianluca Guida sub r1, r1, #2 266b6cbf720SGianluca Guida b .Lmemmove_fl4 267b6cbf720SGianluca Guida 268b6cbf720SGianluca Guida.Lmemmove_fsrcul3: 269b6cbf720SGianluca Guida cmp r2, #0x0c 270b6cbf720SGianluca Guida blt .Lmemmove_fsrcul3loop4 271b6cbf720SGianluca Guida sub r2, r2, #0x0c 27284d9c625SLionel Sambuc push {r4, r5} 273b6cbf720SGianluca Guida 274b6cbf720SGianluca Guida.Lmemmove_fsrcul3loop16: 275b6cbf720SGianluca Guida#ifdef __ARMEB__ 276b6cbf720SGianluca Guida mov r3, lr, lsl #24 277b6cbf720SGianluca Guida#else 278b6cbf720SGianluca Guida mov r3, lr, lsr #24 279b6cbf720SGianluca Guida#endif 280b6cbf720SGianluca Guida ldmia r1!, {r4, r5, r12, lr} 281b6cbf720SGianluca Guida#ifdef __ARMEB__ 282b6cbf720SGianluca Guida orr r3, r3, r4, lsr #8 283b6cbf720SGianluca Guida mov r4, r4, lsl #24 284b6cbf720SGianluca Guida orr r4, r4, r5, lsr #8 285b6cbf720SGianluca Guida mov r5, r5, lsl #24 286b6cbf720SGianluca Guida orr r5, r5, r12, lsr #8 287b6cbf720SGianluca Guida mov r12, r12, lsl #24 288b6cbf720SGianluca Guida orr r12, r12, lr, lsr #8 289b6cbf720SGianluca Guida#else 290b6cbf720SGianluca Guida orr r3, r3, r4, lsl #8 291b6cbf720SGianluca Guida mov r4, r4, lsr #24 292b6cbf720SGianluca Guida orr r4, r4, r5, lsl #8 293b6cbf720SGianluca Guida mov r5, r5, lsr #24 294b6cbf720SGianluca Guida orr r5, r5, r12, lsl #8 295b6cbf720SGianluca Guida mov r12, r12, lsr #24 296b6cbf720SGianluca Guida orr r12, r12, lr, lsl #8 297b6cbf720SGianluca Guida#endif 298b6cbf720SGianluca Guida stmia r0!, {r3-r5, r12} 299b6cbf720SGianluca Guida subs r2, r2, #0x10 300b6cbf720SGianluca Guida bge .Lmemmove_fsrcul3loop16 30184d9c625SLionel Sambuc pop {r4, r5} 302b6cbf720SGianluca Guida adds r2, r2, #0x0c 303b6cbf720SGianluca Guida blt .Lmemmove_fsrcul3l4 304b6cbf720SGianluca Guida 305b6cbf720SGianluca Guida.Lmemmove_fsrcul3loop4: 306b6cbf720SGianluca Guida#ifdef __ARMEB__ 307b6cbf720SGianluca Guida mov r12, lr, lsl #24 308b6cbf720SGianluca Guida#else 309b6cbf720SGianluca Guida mov r12, lr, lsr #24 310b6cbf720SGianluca Guida#endif 311b6cbf720SGianluca Guida ldr lr, [r1], #4 312b6cbf720SGianluca Guida#ifdef __ARMEB__ 313b6cbf720SGianluca Guida orr r12, r12, lr, lsr #8 314b6cbf720SGianluca Guida#else 315b6cbf720SGianluca Guida orr r12, r12, lr, lsl #8 316b6cbf720SGianluca Guida#endif 317b6cbf720SGianluca Guida str r12, [r0], #4 318b6cbf720SGianluca Guida subs r2, r2, #4 319b6cbf720SGianluca Guida bge .Lmemmove_fsrcul3loop4 320b6cbf720SGianluca Guida 321b6cbf720SGianluca Guida.Lmemmove_fsrcul3l4: 322b6cbf720SGianluca Guida sub r1, r1, #1 323b6cbf720SGianluca Guida b .Lmemmove_fl4 324b6cbf720SGianluca Guida 325b6cbf720SGianluca Guida.Lmemmove_backwards: 326b6cbf720SGianluca Guida add r1, r1, r2 327b6cbf720SGianluca Guida add r0, r0, r2 328b6cbf720SGianluca Guida subs r2, r2, #4 329b6cbf720SGianluca Guida blt .Lmemmove_bl4 /* less than 4 bytes */ 330b6cbf720SGianluca Guida ands r12, r0, #3 331b6cbf720SGianluca Guida bne .Lmemmove_bdestul /* oh unaligned destination addr */ 332b6cbf720SGianluca Guida ands r12, r1, #3 333b6cbf720SGianluca Guida bne .Lmemmove_bsrcul /* oh unaligned source addr */ 334b6cbf720SGianluca Guida 335b6cbf720SGianluca Guida.Lmemmove_bt8: 336b6cbf720SGianluca Guida /* We have aligned source and destination */ 337b6cbf720SGianluca Guida subs r2, r2, #8 338b6cbf720SGianluca Guida blt .Lmemmove_bl12 /* less than 12 bytes (4 from above) */ 33984d9c625SLionel Sambuc push {r4, lr} 340b6cbf720SGianluca Guida subs r2, r2, #0x14 /* less than 32 bytes (12 from above) */ 341b6cbf720SGianluca Guida blt .Lmemmove_bl32 342b6cbf720SGianluca Guida 343b6cbf720SGianluca Guida /* blat 32 bytes at a time */ 344b6cbf720SGianluca Guida /* XXX for really big copies perhaps we should use more registers */ 345b6cbf720SGianluca Guida.Lmemmove_bloop32: 346b6cbf720SGianluca Guida ldmdb r1!, {r3, r4, r12, lr} 347b6cbf720SGianluca Guida stmdb r0!, {r3, r4, r12, lr} 348b6cbf720SGianluca Guida ldmdb r1!, {r3, r4, r12, lr} 349b6cbf720SGianluca Guida stmdb r0!, {r3, r4, r12, lr} 350b6cbf720SGianluca Guida subs r2, r2, #0x20 351b6cbf720SGianluca Guida bge .Lmemmove_bloop32 352b6cbf720SGianluca Guida 353b6cbf720SGianluca Guida.Lmemmove_bl32: 354b6cbf720SGianluca Guida cmn r2, #0x10 35584d9c625SLionel Sambuc ldmdbge r1!, {r3, r4, r12, lr} /* blat a remaining 16 bytes */ 35684d9c625SLionel Sambuc stmdbge r0!, {r3, r4, r12, lr} 357b6cbf720SGianluca Guida subge r2, r2, #0x10 358b6cbf720SGianluca Guida adds r2, r2, #0x14 35984d9c625SLionel Sambuc ldmdbge r1!, {r3, r12, lr} /* blat a remaining 12 bytes */ 36084d9c625SLionel Sambuc stmdbge r0!, {r3, r12, lr} 361b6cbf720SGianluca Guida subge r2, r2, #0x0c 36284d9c625SLionel Sambuc pop {r4, lr} 363b6cbf720SGianluca Guida 364b6cbf720SGianluca Guida.Lmemmove_bl12: 365b6cbf720SGianluca Guida adds r2, r2, #8 366b6cbf720SGianluca Guida blt .Lmemmove_bl4 367b6cbf720SGianluca Guida subs r2, r2, #4 368b6cbf720SGianluca Guida ldrlt r3, [r1, #-4]! 369b6cbf720SGianluca Guida strlt r3, [r0, #-4]! 37084d9c625SLionel Sambuc ldmdbge r1!, {r3, r12} 37184d9c625SLionel Sambuc stmdbge r0!, {r3, r12} 372b6cbf720SGianluca Guida subge r2, r2, #4 373b6cbf720SGianluca Guida 374b6cbf720SGianluca Guida.Lmemmove_bl4: 375b6cbf720SGianluca Guida /* less than 4 bytes to go */ 376b6cbf720SGianluca Guida adds r2, r2, #4 377b6cbf720SGianluca Guida RETc(eq) 378b6cbf720SGianluca Guida 379b6cbf720SGianluca Guida /* copy the crud byte at a time */ 380b6cbf720SGianluca Guida cmp r2, #2 381b6cbf720SGianluca Guida ldrb r3, [r1, #-1]! 382b6cbf720SGianluca Guida strb r3, [r0, #-1]! 38384d9c625SLionel Sambuc ldrbge r3, [r1, #-1]! 38484d9c625SLionel Sambuc strbge r3, [r0, #-1]! 38584d9c625SLionel Sambuc ldrbgt r3, [r1, #-1]! 38684d9c625SLionel Sambuc strbgt r3, [r0, #-1]! 387b6cbf720SGianluca Guida RET 388b6cbf720SGianluca Guida 389b6cbf720SGianluca Guida /* erg - unaligned destination */ 390b6cbf720SGianluca Guida.Lmemmove_bdestul: 391b6cbf720SGianluca Guida cmp r12, #2 392b6cbf720SGianluca Guida 393b6cbf720SGianluca Guida /* align destination with byte copies */ 394b6cbf720SGianluca Guida ldrb r3, [r1, #-1]! 395b6cbf720SGianluca Guida strb r3, [r0, #-1]! 39684d9c625SLionel Sambuc ldrbge r3, [r1, #-1]! 39784d9c625SLionel Sambuc strbge r3, [r0, #-1]! 39884d9c625SLionel Sambuc ldrbgt r3, [r1, #-1]! 39984d9c625SLionel Sambuc strbgt r3, [r0, #-1]! 400b6cbf720SGianluca Guida subs r2, r2, r12 401b6cbf720SGianluca Guida blt .Lmemmove_bl4 /* less than 4 bytes to go */ 402b6cbf720SGianluca Guida ands r12, r1, #3 403b6cbf720SGianluca Guida beq .Lmemmove_bt8 /* we have an aligned source */ 404b6cbf720SGianluca Guida 405b6cbf720SGianluca Guida /* erg - unaligned source */ 406b6cbf720SGianluca Guida /* This is where it gets nasty ... */ 407b6cbf720SGianluca Guida.Lmemmove_bsrcul: 408b6cbf720SGianluca Guida bic r1, r1, #3 409b6cbf720SGianluca Guida ldr r3, [r1, #0] 410b6cbf720SGianluca Guida cmp r12, #2 411b6cbf720SGianluca Guida blt .Lmemmove_bsrcul1 412b6cbf720SGianluca Guida beq .Lmemmove_bsrcul2 413b6cbf720SGianluca Guida cmp r2, #0x0c 414b6cbf720SGianluca Guida blt .Lmemmove_bsrcul3loop4 415b6cbf720SGianluca Guida sub r2, r2, #0x0c 41684d9c625SLionel Sambuc push {r4, r5, lr} 417b6cbf720SGianluca Guida 418b6cbf720SGianluca Guida.Lmemmove_bsrcul3loop16: 419b6cbf720SGianluca Guida#ifdef __ARMEB__ 420b6cbf720SGianluca Guida mov lr, r3, lsr #8 421b6cbf720SGianluca Guida#else 422b6cbf720SGianluca Guida mov lr, r3, lsl #8 423b6cbf720SGianluca Guida#endif 424b6cbf720SGianluca Guida ldmdb r1!, {r3-r5, r12} 425b6cbf720SGianluca Guida#ifdef __ARMEB__ 426b6cbf720SGianluca Guida orr lr, lr, r12, lsl #24 427b6cbf720SGianluca Guida mov r12, r12, lsr #8 428b6cbf720SGianluca Guida orr r12, r12, r5, lsl #24 429b6cbf720SGianluca Guida mov r5, r5, lsr #8 430b6cbf720SGianluca Guida orr r5, r5, r4, lsl #24 431b6cbf720SGianluca Guida mov r4, r4, lsr #8 432b6cbf720SGianluca Guida orr r4, r4, r3, lsl #24 433b6cbf720SGianluca Guida#else 434b6cbf720SGianluca Guida orr lr, lr, r12, lsr #24 435b6cbf720SGianluca Guida mov r12, r12, lsl #8 436b6cbf720SGianluca Guida orr r12, r12, r5, lsr #24 437b6cbf720SGianluca Guida mov r5, r5, lsl #8 438b6cbf720SGianluca Guida orr r5, r5, r4, lsr #24 439b6cbf720SGianluca Guida mov r4, r4, lsl #8 440b6cbf720SGianluca Guida orr r4, r4, r3, lsr #24 441b6cbf720SGianluca Guida#endif 442b6cbf720SGianluca Guida stmdb r0!, {r4, r5, r12, lr} 443b6cbf720SGianluca Guida subs r2, r2, #0x10 444b6cbf720SGianluca Guida bge .Lmemmove_bsrcul3loop16 44584d9c625SLionel Sambuc pop {r4, r5, lr} 446b6cbf720SGianluca Guida adds r2, r2, #0x0c 447b6cbf720SGianluca Guida blt .Lmemmove_bsrcul3l4 448b6cbf720SGianluca Guida 449b6cbf720SGianluca Guida.Lmemmove_bsrcul3loop4: 450b6cbf720SGianluca Guida#ifdef __ARMEB__ 451b6cbf720SGianluca Guida mov r12, r3, lsr #8 452b6cbf720SGianluca Guida#else 453b6cbf720SGianluca Guida mov r12, r3, lsl #8 454b6cbf720SGianluca Guida#endif 455b6cbf720SGianluca Guida ldr r3, [r1, #-4]! 456b6cbf720SGianluca Guida#ifdef __ARMEB__ 457b6cbf720SGianluca Guida orr r12, r12, r3, lsl #24 458b6cbf720SGianluca Guida#else 459b6cbf720SGianluca Guida orr r12, r12, r3, lsr #24 460b6cbf720SGianluca Guida#endif 461b6cbf720SGianluca Guida str r12, [r0, #-4]! 462b6cbf720SGianluca Guida subs r2, r2, #4 463b6cbf720SGianluca Guida bge .Lmemmove_bsrcul3loop4 464b6cbf720SGianluca Guida 465b6cbf720SGianluca Guida.Lmemmove_bsrcul3l4: 466b6cbf720SGianluca Guida add r1, r1, #3 467b6cbf720SGianluca Guida b .Lmemmove_bl4 468b6cbf720SGianluca Guida 469b6cbf720SGianluca Guida.Lmemmove_bsrcul2: 470b6cbf720SGianluca Guida cmp r2, #0x0c 471b6cbf720SGianluca Guida blt .Lmemmove_bsrcul2loop4 472b6cbf720SGianluca Guida sub r2, r2, #0x0c 47384d9c625SLionel Sambuc push {r4, r5, lr} 474b6cbf720SGianluca Guida 475b6cbf720SGianluca Guida.Lmemmove_bsrcul2loop16: 476b6cbf720SGianluca Guida#ifdef __ARMEB__ 477b6cbf720SGianluca Guida mov lr, r3, lsr #16 478b6cbf720SGianluca Guida#else 479b6cbf720SGianluca Guida mov lr, r3, lsl #16 480b6cbf720SGianluca Guida#endif 481b6cbf720SGianluca Guida ldmdb r1!, {r3-r5, r12} 482b6cbf720SGianluca Guida#ifdef __ARMEB__ 483b6cbf720SGianluca Guida orr lr, lr, r12, lsl #16 484b6cbf720SGianluca Guida mov r12, r12, lsr #16 485b6cbf720SGianluca Guida orr r12, r12, r5, lsl #16 486b6cbf720SGianluca Guida mov r5, r5, lsr #16 487b6cbf720SGianluca Guida orr r5, r5, r4, lsl #16 488b6cbf720SGianluca Guida mov r4, r4, lsr #16 489b6cbf720SGianluca Guida orr r4, r4, r3, lsl #16 490b6cbf720SGianluca Guida#else 491b6cbf720SGianluca Guida orr lr, lr, r12, lsr #16 492b6cbf720SGianluca Guida mov r12, r12, lsl #16 493b6cbf720SGianluca Guida orr r12, r12, r5, lsr #16 494b6cbf720SGianluca Guida mov r5, r5, lsl #16 495b6cbf720SGianluca Guida orr r5, r5, r4, lsr #16 496b6cbf720SGianluca Guida mov r4, r4, lsl #16 497b6cbf720SGianluca Guida orr r4, r4, r3, lsr #16 498b6cbf720SGianluca Guida#endif 499b6cbf720SGianluca Guida stmdb r0!, {r4, r5, r12, lr} 500b6cbf720SGianluca Guida subs r2, r2, #0x10 501b6cbf720SGianluca Guida bge .Lmemmove_bsrcul2loop16 50284d9c625SLionel Sambuc pop {r4, r5, lr} 503b6cbf720SGianluca Guida adds r2, r2, #0x0c 504b6cbf720SGianluca Guida blt .Lmemmove_bsrcul2l4 505b6cbf720SGianluca Guida 506b6cbf720SGianluca Guida.Lmemmove_bsrcul2loop4: 507b6cbf720SGianluca Guida#ifdef __ARMEB__ 508b6cbf720SGianluca Guida mov r12, r3, lsr #16 509b6cbf720SGianluca Guida#else 510b6cbf720SGianluca Guida mov r12, r3, lsl #16 511b6cbf720SGianluca Guida#endif 512b6cbf720SGianluca Guida ldr r3, [r1, #-4]! 513b6cbf720SGianluca Guida#ifdef __ARMEB__ 514b6cbf720SGianluca Guida orr r12, r12, r3, lsl #16 515b6cbf720SGianluca Guida#else 516b6cbf720SGianluca Guida orr r12, r12, r3, lsr #16 517b6cbf720SGianluca Guida#endif 518b6cbf720SGianluca Guida str r12, [r0, #-4]! 519b6cbf720SGianluca Guida subs r2, r2, #4 520b6cbf720SGianluca Guida bge .Lmemmove_bsrcul2loop4 521b6cbf720SGianluca Guida 522b6cbf720SGianluca Guida.Lmemmove_bsrcul2l4: 523b6cbf720SGianluca Guida add r1, r1, #2 524b6cbf720SGianluca Guida b .Lmemmove_bl4 525b6cbf720SGianluca Guida 526b6cbf720SGianluca Guida.Lmemmove_bsrcul1: 527b6cbf720SGianluca Guida cmp r2, #0x0c 528b6cbf720SGianluca Guida blt .Lmemmove_bsrcul1loop4 529b6cbf720SGianluca Guida sub r2, r2, #0x0c 53084d9c625SLionel Sambuc push {r4, r5, lr} 531b6cbf720SGianluca Guida 532b6cbf720SGianluca Guida.Lmemmove_bsrcul1loop32: 533b6cbf720SGianluca Guida#ifdef __ARMEB__ 534b6cbf720SGianluca Guida mov lr, r3, lsr #24 535b6cbf720SGianluca Guida#else 536b6cbf720SGianluca Guida mov lr, r3, lsl #24 537b6cbf720SGianluca Guida#endif 538b6cbf720SGianluca Guida ldmdb r1!, {r3-r5, r12} 539b6cbf720SGianluca Guida#ifdef __ARMEB__ 540b6cbf720SGianluca Guida orr lr, lr, r12, lsl #8 541b6cbf720SGianluca Guida mov r12, r12, lsr #24 542b6cbf720SGianluca Guida orr r12, r12, r5, lsl #8 543b6cbf720SGianluca Guida mov r5, r5, lsr #24 544b6cbf720SGianluca Guida orr r5, r5, r4, lsl #8 545b6cbf720SGianluca Guida mov r4, r4, lsr #24 546b6cbf720SGianluca Guida orr r4, r4, r3, lsl #8 547b6cbf720SGianluca Guida#else 548b6cbf720SGianluca Guida orr lr, lr, r12, lsr #8 549b6cbf720SGianluca Guida mov r12, r12, lsl #24 550b6cbf720SGianluca Guida orr r12, r12, r5, lsr #8 551b6cbf720SGianluca Guida mov r5, r5, lsl #24 552b6cbf720SGianluca Guida orr r5, r5, r4, lsr #8 553b6cbf720SGianluca Guida mov r4, r4, lsl #24 554b6cbf720SGianluca Guida orr r4, r4, r3, lsr #8 555b6cbf720SGianluca Guida#endif 556b6cbf720SGianluca Guida stmdb r0!, {r4, r5, r12, lr} 557b6cbf720SGianluca Guida subs r2, r2, #0x10 558b6cbf720SGianluca Guida bge .Lmemmove_bsrcul1loop32 55984d9c625SLionel Sambuc pop {r4, r5, lr} 560b6cbf720SGianluca Guida adds r2, r2, #0x0c 561b6cbf720SGianluca Guida blt .Lmemmove_bsrcul1l4 562b6cbf720SGianluca Guida 563b6cbf720SGianluca Guida.Lmemmove_bsrcul1loop4: 564b6cbf720SGianluca Guida#ifdef __ARMEB__ 565b6cbf720SGianluca Guida mov r12, r3, lsr #24 566b6cbf720SGianluca Guida#else 567b6cbf720SGianluca Guida mov r12, r3, lsl #24 568b6cbf720SGianluca Guida#endif 569b6cbf720SGianluca Guida ldr r3, [r1, #-4]! 570b6cbf720SGianluca Guida#ifdef __ARMEB__ 571b6cbf720SGianluca Guida orr r12, r12, r3, lsl #8 572b6cbf720SGianluca Guida#else 573b6cbf720SGianluca Guida orr r12, r12, r3, lsr #8 574b6cbf720SGianluca Guida#endif 575b6cbf720SGianluca Guida str r12, [r0, #-4]! 576b6cbf720SGianluca Guida subs r2, r2, #4 577b6cbf720SGianluca Guida bge .Lmemmove_bsrcul1loop4 578b6cbf720SGianluca Guida 579b6cbf720SGianluca Guida.Lmemmove_bsrcul1l4: 580b6cbf720SGianluca Guida add r1, r1, #1 581b6cbf720SGianluca Guida b .Lmemmove_bl4 58284d9c625SLionel Sambuc#ifndef _BCOPY 58384d9c625SLionel SambucEND(memmove) 58484d9c625SLionel Sambuc#else 58584d9c625SLionel SambucEND(bcopy) 58684d9c625SLionel Sambuc#endif 58784d9c625SLionel Sambuc 588*0a6a1f1dSLionel Sambuc#if defined(__ARM_EABI__) && !defined(BCOPY) && !defined(_RUMPKERNEL) 58984d9c625SLionel SambucSTRONG_ALIAS(__aeabi_memmove, memmove) 590*0a6a1f1dSLionel SambucSTRONG_ALIAS(__aeabi_memmove4, memmove) 591*0a6a1f1dSLionel SambucSTRONG_ALIAS(__aeabi_memmove8, memmove) 59284d9c625SLionel Sambuc#endif 593