1/*
2 * Copyright (c) 2014 Travis Geiselbrecht
3 *
4 * Use of this source code is governed by a MIT-style
5 * license that can be found in the LICENSE file or at
6 * https://opensource.org/licenses/MIT
7 */
8#include <lk/asm.h>
9#include <arch/arm/cores.h>
10
11.text
12.syntax unified
13.thumb
14.align 2
15
16/* void bcopy(const void *src, void *dest, size_t n); */
17FUNCTION(bcopy)
18    // swap args for bcopy
19    mov     r12, r0
20    mov     r0, r1
21    mov     r1, r12
22
23/* void *memcpy(void *dest, const void *src, size_t count) */
24FUNCTION(memcpy)
25    push    { r0, r14 }
26
27    // test for zero length or pointers being equivalent
28    cbz     r2, .L_done
29    cmp     r0, r1
30    beq     .L_done
31
32    // check for a short copy len
33    cmp     r2, #16
34    blt     .L_bytewise
35
36    // check to see if the pointers are similarly dword aligned
37    eors    r3, r0, r1
38    ands    r3, #7
39    beq     .L_prepare_dword
40
41    // see how many bytes we need to move to align dest to word boundary
42    and     r3, r0, #3
43    cbz     r3, .L_prepare_wordwise
44    rsb     r3, #4
45    subs    r2, r3
46
47    .align 2
48.L_bytewise_align:
49    // bytewise to align memcpy
50    ldrb    r12, [r1], #1
51    subs    r3, r3, #1
52    strb    r12, [r0], #1
53    bgt     .L_bytewise_align
54
55.L_prepare_wordwise:
56    // load the number of words left
57    lsrs    r3, r2, #2
58
59    .align 2
60.L_wordwise:
61    // wordwise copy
62    ldr     r12, [r1], #4
63    subs    r3, r3, #1
64    str     r12, [r0], #4
65    bgt     .L_wordwise
66
67    // remaining bytes
68    ands     r2, #3
69    beq     .L_done
70
71    .align 2
72.L_bytewise:
73    // simple bytewise copy
74    ldrb    r12, [r1], #1
75    subs    r2, r2, #1
76    strb    r12, [r0], #1
77    bgt     .L_bytewise
78
79.L_done:
80    pop     { r0, pc }
81
82// Handle copying by dword (8 bytes at a time) increments
83.L_prepare_dword:
84    // see how many bytes we need to move to align dest to dword boundary
85    and     r3, r0, #7
86    cbz     r3, .L_prepare_dwordwise
87    rsb     r3, #8
88    subs    r2, r3
89
90    .align 2
91.L_bytewise_align_dword:
92    // bytewise to align memcpy
93    ldrb    r12, [r1], #1
94    subs    r3, r3, #1
95    strb    r12, [r0], #1
96    bgt     .L_bytewise_align_dword
97
98.L_prepare_dwordwise:
99    // load the number of dwords left
100    lsrs    r3, r2, #3
101
102    push    { r5 }
103
104    .align 2
105.L_dwordwise:
106    // dwordwise copy
107    ldrd    r5, r12, [r1], #8
108    subs    r3, r3, #1
109    strd    r5, r12, [r0], #8
110    bgt     .L_dwordwise
111
112    pop     { r5 }
113
114    // remaining bytes
115    ands     r2, #7
116    beq     .L_done
117
118    // finish the remaining bytes and exit
119    b       .L_bytewise
120
121