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