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 bzero(void *s, size_t n); */
17FUNCTION(bzero)
18    mov     r2, r1
19    movs    r1, #0
20
21/* void *memset(void *s, int c, size_t n); */
22FUNCTION(memset)
23    // save the original pointer
24    push    { r0, lr }
25
26    // check for zero length
27    cbz     r2, .L_done
28
29    // short memsets aren't worth optimizing and make sure we have
30    // enough headroom to try to do dwordwise move optimization
31    cmp     r2, #16
32    blt     .L_bytewise
33
34    // see how many bytes we need to move to align to dword boundaries
35    and     r3, r0, #7
36    cbz     r3, .L_prepare_dwordwise
37    rsb     r3, #8
38    subs    r2, r3
39
40.L_bytewise_align:
41    // bytewise to align memset
42    subs    r3, r3, #1
43    strb    r1, [r0], #1
44    bgt     .L_bytewise_align
45
46.L_prepare_dwordwise:
47    // fill a pair of 32 bit registers with the 8 bit value
48    uxtb    r1, r1
49    orr     r1, r1, r1, lsl #8
50    orr     r1, r1, r1, lsl #16
51    mov     r12, r1
52
53    // load the number of dwords left
54    lsrs    r3, r2, #3
55
56.L_dwordwise:
57    // dwordwise memset
58    subs    r3, r3, #1
59    strd    r1, r12, [r0], #8
60    bgt     .L_dwordwise
61
62    // remaining bytes
63    ands     r2, #7
64    beq     .L_done
65
66.L_bytewise:
67    // bytewise memset
68    subs    r2, r2, #1
69    strb    r1, [r0], #1
70    bgt     .L_bytewise
71
72.L_done:
73    // restore the base pointer as return value
74    pop     { r0, pc }
75
76