1f9f848faSopenharmony_ci/* $NetBSD: memcpy_arm.S,v 1.1 2003/10/14 07:51:45 scw Exp $ */ 2f9f848faSopenharmony_ci 3f9f848faSopenharmony_ci/*- 4f9f848faSopenharmony_ci * Copyright (c) 1997 The NetBSD Foundation, Inc. 5f9f848faSopenharmony_ci * All rights reserved. 6f9f848faSopenharmony_ci * 7f9f848faSopenharmony_ci * This code is derived from software contributed to The NetBSD Foundation 8f9f848faSopenharmony_ci * by Neil A. Carson and Mark Brinicombe 9f9f848faSopenharmony_ci * 10f9f848faSopenharmony_ci * Redistribution and use in source and binary forms, with or without 11f9f848faSopenharmony_ci * modification, are permitted provided that the following conditions 12f9f848faSopenharmony_ci * are met: 13f9f848faSopenharmony_ci * 1. Redistributions of source code must retain the above copyright 14f9f848faSopenharmony_ci * notice, this list of conditions and the following disclaimer. 15f9f848faSopenharmony_ci * 2. Redistributions in binary form must reproduce the above copyright 16f9f848faSopenharmony_ci * notice, this list of conditions and the following disclaimer in the 17f9f848faSopenharmony_ci * documentation and/or other materials provided with the distribution. 18f9f848faSopenharmony_ci * 19f9f848faSopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20f9f848faSopenharmony_ci * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21f9f848faSopenharmony_ci * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22f9f848faSopenharmony_ci * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23f9f848faSopenharmony_ci * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24f9f848faSopenharmony_ci * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25f9f848faSopenharmony_ci * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26f9f848faSopenharmony_ci * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27f9f848faSopenharmony_ci * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28f9f848faSopenharmony_ci * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29f9f848faSopenharmony_ci * POSSIBILITY OF SUCH DAMAGE. 30f9f848faSopenharmony_ci */ 31f9f848faSopenharmony_ci 32f9f848faSopenharmony_ci#include "asm.h" 33f9f848faSopenharmony_ci 34f9f848faSopenharmony_ci// We do not need to check whether the addresses are in the 35f9f848faSopenharmony_ci// kernel or virtual address spaces, since we only access them 36f9f848faSopenharmony_ci// using user privileges. 37f9f848faSopenharmony_ci 38f9f848faSopenharmony_ci.syntax unified 39f9f848faSopenharmony_ci.arm 40f9f848faSopenharmony_ci 41f9f848faSopenharmony_ci// size_t _arm_user_copy(void *dst, const void *src, size_t len) 42f9f848faSopenharmony_ciFUNCTION(_arm_user_copy) 43f9f848faSopenharmony_ci /* save leaf functions having to store this away */ 44f9f848faSopenharmony_ci stmdb sp!, {r0, r1, r2, lr} /* _arm_user_copy() returns dest addr */ 45f9f848faSopenharmony_ci 46f9f848faSopenharmony_ci subs r2, r2, #4 47f9f848faSopenharmony_ci blt .Lmemcpy_l4 /* less than 4 bytes */ 48f9f848faSopenharmony_ci ands r12, r0, #3 49f9f848faSopenharmony_ci bne .Lmemcpy_destul /* oh unaligned destination addr */ 50f9f848faSopenharmony_ci ands r12, r1, #3 51f9f848faSopenharmony_ci bne .Lmemcpy_srcul /* oh unaligned source addr */ 52f9f848faSopenharmony_ci 53f9f848faSopenharmony_ci.Lmemcpy_t8: 54f9f848faSopenharmony_ci /* We have aligned source and destination */ 55f9f848faSopenharmony_ci subs r2, r2, #8 56f9f848faSopenharmony_ci blt .Lmemcpy_l12 /* less than 12 bytes (4 from above) */ 57f9f848faSopenharmony_ci subs r2, r2, #0x14 58f9f848faSopenharmony_ci blt .Lmemcpy_l32 /* less than 32 bytes (12 from above) */ 59f9f848faSopenharmony_ci stmdb sp!, {r4} /* borrow r4 */ 60f9f848faSopenharmony_ci 61f9f848faSopenharmony_ci /* blat 32 bytes at a time */ 62f9f848faSopenharmony_ci /* XXX for really big copies perhaps we should use more registers */ 63f9f848faSopenharmony_ci.Lmemcpy_loop32: 64f9f848faSopenharmony_ci0: ldmia r1!, {r3, r4, r12, lr} 65f9f848faSopenharmony_ci1: stmia r0!, {r3, r4, r12, lr} 66f9f848faSopenharmony_ci2: ldmia r1!, {r3, r4, r12, lr} 67f9f848faSopenharmony_ci3: stmia r0!, {r3, r4, r12, lr} 68f9f848faSopenharmony_ci subs r2, r2, #0x20 69f9f848faSopenharmony_ci bge .Lmemcpy_loop32 70f9f848faSopenharmony_ci 71f9f848faSopenharmony_ci cmn r2, #0x10 72f9f848faSopenharmony_ci4: ldmiage r1!, {r3, r4, r12, lr} /* blat a remaining 16 bytes */ 73f9f848faSopenharmony_ci5: stmiage r0!, {r3, r4, r12, lr} 74f9f848faSopenharmony_ci subge r2, r2, #0x10 75f9f848faSopenharmony_ci ldmia sp!, {r4} /* return r4 */ 76f9f848faSopenharmony_ci 77f9f848faSopenharmony_ci.Lmemcpy_l32: 78f9f848faSopenharmony_ci adds r2, r2, #0x14 79f9f848faSopenharmony_ci 80f9f848faSopenharmony_ci /* blat 12 bytes at a time */ 81f9f848faSopenharmony_ci.Lmemcpy_loop12: 82f9f848faSopenharmony_ci6: ldmiage r1!, {r3, r12, lr} 83f9f848faSopenharmony_ci7: stmiage r0!, {r3, r12, lr} 84f9f848faSopenharmony_ci subsge r2, r2, #0x0c 85f9f848faSopenharmony_ci bge .Lmemcpy_loop12 86f9f848faSopenharmony_ci 87f9f848faSopenharmony_ci.Lmemcpy_l12: 88f9f848faSopenharmony_ci adds r2, r2, #8 89f9f848faSopenharmony_ci blt .Lmemcpy_l4 90f9f848faSopenharmony_ci 91f9f848faSopenharmony_ci subs r2, r2, #4 92f9f848faSopenharmony_ci8: ldrlt r3, [r1], #4 93f9f848faSopenharmony_ci9: strlt r3, [r0], #4 94f9f848faSopenharmony_ci10: ldmiage r1!, {r3, r12} 95f9f848faSopenharmony_ci11: stmiage r0!, {r3, r12} 96f9f848faSopenharmony_ci subge r2, r2, #4 97f9f848faSopenharmony_ci 98f9f848faSopenharmony_ci.Lmemcpy_l4: 99f9f848faSopenharmony_ci /* less than 4 bytes to go */ 100f9f848faSopenharmony_ci adds r2, r2, #4 101f9f848faSopenharmony_ci beq .Lmemcpy_return 102f9f848faSopenharmony_ci /* copy the crud byte at a time */ 103f9f848faSopenharmony_ci cmp r2, #2 104f9f848faSopenharmony_ci12: ldrb r3, [r1], #1 105f9f848faSopenharmony_ci13: strb r3, [r0], #1 106f9f848faSopenharmony_ci14: ldrbge r3, [r1], #1 107f9f848faSopenharmony_ci15: strbge r3, [r0], #1 108f9f848faSopenharmony_ci16: ldrbgt r3, [r1], #1 109f9f848faSopenharmony_ci17: strbgt r3, [r0], #1 110f9f848faSopenharmony_ci 111f9f848faSopenharmony_ci.Lmemcpy_return: 112f9f848faSopenharmony_ci ldmia sp!, {r0, r1, r2, lr} 113f9f848faSopenharmony_ci mov r0, 0 114f9f848faSopenharmony_ci bx lr 115f9f848faSopenharmony_ci 116f9f848faSopenharmony_ci /* erg - unaligned destination */ 117f9f848faSopenharmony_ci.Lmemcpy_destul: 118f9f848faSopenharmony_ci rsb r12, r12, #4 119f9f848faSopenharmony_ci cmp r12, #2 120f9f848faSopenharmony_ci 121f9f848faSopenharmony_ci /* align destination with byte copies */ 122f9f848faSopenharmony_ci18: ldrb r3, [r1], #1 123f9f848faSopenharmony_ci19: strb r3, [r0], #1 124f9f848faSopenharmony_ci20: ldrbge r3, [r1], #1 125f9f848faSopenharmony_ci21: strbge r3, [r0], #1 126f9f848faSopenharmony_ci22: ldrbgt r3, [r1], #1 127f9f848faSopenharmony_ci23: strbgt r3, [r0], #1 128f9f848faSopenharmony_ci subs r2, r2, r12 129f9f848faSopenharmony_ci blt .Lmemcpy_l4 /* less the 4 bytes */ 130f9f848faSopenharmony_ci 131f9f848faSopenharmony_ci ands r12, r1, #3 132f9f848faSopenharmony_ci beq .Lmemcpy_t8 /* we have an aligned source */ 133f9f848faSopenharmony_ci 134f9f848faSopenharmony_ci /* erg - unaligned source */ 135f9f848faSopenharmony_ci /* This is where it gets nasty ... */ 136f9f848faSopenharmony_ci.Lmemcpy_srcul: 137f9f848faSopenharmony_ci bic r1, r1, #3 138f9f848faSopenharmony_ci24: ldr lr, [r1], #4 139f9f848faSopenharmony_ci cmp r12, #2 140f9f848faSopenharmony_ci bgt .Lmemcpy_srcul3 141f9f848faSopenharmony_ci beq .Lmemcpy_srcul2 142f9f848faSopenharmony_ci cmp r2, #0x0c 143f9f848faSopenharmony_ci blt .Lmemcpy_srcul1loop4 144f9f848faSopenharmony_ci sub r2, r2, #0x0c 145f9f848faSopenharmony_ci stmdb sp!, {r4, r5} 146f9f848faSopenharmony_ci 147f9f848faSopenharmony_ci.Lmemcpy_srcul1loop16: 148f9f848faSopenharmony_ci mov r3, lr, lsr #8 149f9f848faSopenharmony_ci25: ldmia r1!, {r4, r5, r12, lr} 150f9f848faSopenharmony_ci orr r3, r3, r4, lsl #24 151f9f848faSopenharmony_ci mov r4, r4, lsr #8 152f9f848faSopenharmony_ci orr r4, r4, r5, lsl #24 153f9f848faSopenharmony_ci mov r5, r5, lsr #8 154f9f848faSopenharmony_ci orr r5, r5, r12, lsl #24 155f9f848faSopenharmony_ci mov r12, r12, lsr #8 156f9f848faSopenharmony_ci orr r12, r12, lr, lsl #24 157f9f848faSopenharmony_ci26: stmia r0!, {r3-r5, r12} 158f9f848faSopenharmony_ci subs r2, r2, #0x10 159f9f848faSopenharmony_ci bge .Lmemcpy_srcul1loop16 160f9f848faSopenharmony_ci ldmia sp!, {r4, r5} 161f9f848faSopenharmony_ci adds r2, r2, #0x0c 162f9f848faSopenharmony_ci blt .Lmemcpy_srcul1l4 163f9f848faSopenharmony_ci 164f9f848faSopenharmony_ci.Lmemcpy_srcul1loop4: 165f9f848faSopenharmony_ci mov r12, lr, lsr #8 166f9f848faSopenharmony_ci27: ldr lr, [r1], #4 167f9f848faSopenharmony_ci orr r12, r12, lr, lsl #24 168f9f848faSopenharmony_ci28: str r12, [r0], #4 169f9f848faSopenharmony_ci subs r2, r2, #4 170f9f848faSopenharmony_ci bge .Lmemcpy_srcul1loop4 171f9f848faSopenharmony_ci 172f9f848faSopenharmony_ci.Lmemcpy_srcul1l4: 173f9f848faSopenharmony_ci sub r1, r1, #3 174f9f848faSopenharmony_ci b .Lmemcpy_l4 175f9f848faSopenharmony_ci 176f9f848faSopenharmony_ci.Lmemcpy_srcul2: 177f9f848faSopenharmony_ci cmp r2, #0x0c 178f9f848faSopenharmony_ci blt .Lmemcpy_srcul2loop4 179f9f848faSopenharmony_ci sub r2, r2, #0x0c 180f9f848faSopenharmony_ci stmdb sp!, {r4, r5} 181f9f848faSopenharmony_ci 182f9f848faSopenharmony_ci.Lmemcpy_srcul2loop16: 183f9f848faSopenharmony_ci mov r3, lr, lsr #16 184f9f848faSopenharmony_ci29: ldmia r1!, {r4, r5, r12, lr} 185f9f848faSopenharmony_ci orr r3, r3, r4, lsl #16 186f9f848faSopenharmony_ci mov r4, r4, lsr #16 187f9f848faSopenharmony_ci orr r4, r4, r5, lsl #16 188f9f848faSopenharmony_ci mov r5, r5, lsr #16 189f9f848faSopenharmony_ci orr r5, r5, r12, lsl #16 190f9f848faSopenharmony_ci mov r12, r12, lsr #16 191f9f848faSopenharmony_ci orr r12, r12, lr, lsl #16 192f9f848faSopenharmony_ci30: stmia r0!, {r3-r5, r12} 193f9f848faSopenharmony_ci subs r2, r2, #0x10 194f9f848faSopenharmony_ci bge .Lmemcpy_srcul2loop16 195f9f848faSopenharmony_ci ldmia sp!, {r4, r5} 196f9f848faSopenharmony_ci adds r2, r2, #0x0c 197f9f848faSopenharmony_ci blt .Lmemcpy_srcul2l4 198f9f848faSopenharmony_ci 199f9f848faSopenharmony_ci.Lmemcpy_srcul2loop4: 200f9f848faSopenharmony_ci mov r12, lr, lsr #16 201f9f848faSopenharmony_ci31: ldr lr, [r1], #4 202f9f848faSopenharmony_ci orr r12, r12, lr, lsl #16 203f9f848faSopenharmony_ci32: str r12, [r0], #4 204f9f848faSopenharmony_ci subs r2, r2, #4 205f9f848faSopenharmony_ci bge .Lmemcpy_srcul2loop4 206f9f848faSopenharmony_ci 207f9f848faSopenharmony_ci.Lmemcpy_srcul2l4: 208f9f848faSopenharmony_ci sub r1, r1, #2 209f9f848faSopenharmony_ci b .Lmemcpy_l4 210f9f848faSopenharmony_ci 211f9f848faSopenharmony_ci.Lmemcpy_srcul3: 212f9f848faSopenharmony_ci cmp r2, #0x0c 213f9f848faSopenharmony_ci blt .Lmemcpy_srcul3loop4 214f9f848faSopenharmony_ci sub r2, r2, #0x0c 215f9f848faSopenharmony_ci stmdb sp!, {r4, r5} 216f9f848faSopenharmony_ci 217f9f848faSopenharmony_ci.Lmemcpy_srcul3loop16: 218f9f848faSopenharmony_ci mov r3, lr, lsr #24 219f9f848faSopenharmony_ci33: ldmia r1!, {r4, r5, r12, lr} 220f9f848faSopenharmony_ci orr r3, r3, r4, lsl #8 221f9f848faSopenharmony_ci mov r4, r4, lsr #24 222f9f848faSopenharmony_ci orr r4, r4, r5, lsl #8 223f9f848faSopenharmony_ci mov r5, r5, lsr #24 224f9f848faSopenharmony_ci orr r5, r5, r12, lsl #8 225f9f848faSopenharmony_ci mov r12, r12, lsr #24 226f9f848faSopenharmony_ci orr r12, r12, lr, lsl #8 227f9f848faSopenharmony_ci34: stmia r0!, {r3-r5, r12} 228f9f848faSopenharmony_ci subs r2, r2, #0x10 229f9f848faSopenharmony_ci bge .Lmemcpy_srcul3loop16 230f9f848faSopenharmony_ci ldmia sp!, {r4, r5} 231f9f848faSopenharmony_ci adds r2, r2, #0x0c 232f9f848faSopenharmony_ci blt .Lmemcpy_srcul3l4 233f9f848faSopenharmony_ci 234f9f848faSopenharmony_ci.Lmemcpy_srcul3loop4: 235f9f848faSopenharmony_ci mov r12, lr, lsr #24 236f9f848faSopenharmony_ci35: ldr lr, [r1], #4 237f9f848faSopenharmony_ci orr r12, r12, lr, lsl #8 238f9f848faSopenharmony_ci36: str r12, [r0], #4 239f9f848faSopenharmony_ci subs r2, r2, #4 240f9f848faSopenharmony_ci bge .Lmemcpy_srcul3loop4 241f9f848faSopenharmony_ci 242f9f848faSopenharmony_ci.Lmemcpy_srcul3l4: 243f9f848faSopenharmony_ci sub r1, r1, #1 244f9f848faSopenharmony_ci b .Lmemcpy_l4 245f9f848faSopenharmony_ci 246f9f848faSopenharmony_ci.Lfix_return1: 247f9f848faSopenharmony_ci ldmia sp!, {r4} 248f9f848faSopenharmony_ci.Lfix_return2: 249f9f848faSopenharmony_ci ldmia sp!, {r0, r1} 250f9f848faSopenharmony_ci cmp r0, r1 251f9f848faSopenharmony_ci bhs .Lfix_return 252f9f848faSopenharmony_ci sub r0, r2, r0 253f9f848faSopenharmony_ci b .Lfix_return_done 254f9f848faSopenharmony_ci.Lfix_return: 255f9f848faSopenharmony_ci sub r0, r2, r1 256f9f848faSopenharmony_ci.Lfix_return_done: 257f9f848faSopenharmony_ci ldmia sp!, {r2, lr} 258f9f848faSopenharmony_ci sub r0, r2, r0 259f9f848faSopenharmony_ci bx lr 260f9f848faSopenharmony_ci.Lfix_return3: 261f9f848faSopenharmony_ci ldmia sp!, {r4, r5} 262f9f848faSopenharmony_ci b .Lfix_return2 263f9f848faSopenharmony_ci 264f9f848faSopenharmony_ci.pushsection __exc_table, "a" 265f9f848faSopenharmony_ci .long 0b, .Lfix_return1 266f9f848faSopenharmony_ci .long 1b, .Lfix_return1 267f9f848faSopenharmony_ci .long 2b, .Lfix_return1 268f9f848faSopenharmony_ci .long 3b, .Lfix_return1 269f9f848faSopenharmony_ci .long 4b, .Lfix_return1 270f9f848faSopenharmony_ci .long 5b, .Lfix_return1 271f9f848faSopenharmony_ci .long 6b, .Lfix_return2 272f9f848faSopenharmony_ci .long 7b, .Lfix_return2 273f9f848faSopenharmony_ci .long 8b, .Lfix_return2 274f9f848faSopenharmony_ci .long 9b, .Lfix_return2 275f9f848faSopenharmony_ci .long 10b, .Lfix_return2 276f9f848faSopenharmony_ci .long 11b, .Lfix_return2 277f9f848faSopenharmony_ci .long 12b, .Lfix_return2 278f9f848faSopenharmony_ci .long 13b, .Lfix_return2 279f9f848faSopenharmony_ci .long 14b, .Lfix_return2 280f9f848faSopenharmony_ci .long 15b, .Lfix_return2 281f9f848faSopenharmony_ci .long 16b, .Lfix_return2 282f9f848faSopenharmony_ci .long 17b, .Lfix_return2 283f9f848faSopenharmony_ci .long 18b, .Lfix_return2 284f9f848faSopenharmony_ci .long 19b, .Lfix_return2 285f9f848faSopenharmony_ci .long 20b, .Lfix_return2 286f9f848faSopenharmony_ci .long 21b, .Lfix_return2 287f9f848faSopenharmony_ci .long 22b, .Lfix_return2 288f9f848faSopenharmony_ci .long 23b, .Lfix_return2 289f9f848faSopenharmony_ci .long 24b, .Lfix_return2 290f9f848faSopenharmony_ci .long 25b, .Lfix_return3 291f9f848faSopenharmony_ci .long 26b, .Lfix_return3 292f9f848faSopenharmony_ci .long 27b, .Lfix_return2 293f9f848faSopenharmony_ci .long 28b, .Lfix_return2 294f9f848faSopenharmony_ci .long 29b, .Lfix_return3 295f9f848faSopenharmony_ci .long 30b, .Lfix_return3 296f9f848faSopenharmony_ci .long 31b, .Lfix_return2 297f9f848faSopenharmony_ci .long 32b, .Lfix_return2 298f9f848faSopenharmony_ci .long 33b, .Lfix_return3 299f9f848faSopenharmony_ci .long 34b, .Lfix_return3 300f9f848faSopenharmony_ci .long 35b, .Lfix_return2 301f9f848faSopenharmony_ci .long 36b, .Lfix_return2 302f9f848faSopenharmony_ci.popsection 303