710f6f582cadae906ef427e0c309624090a83e02
[platform/kernel/u-boot.git] / arch / arm / lib / memset-arm64.S
1 /* SPDX-License-Identifier: MIT */
2 /*
3  * memset - fill memory with a constant byte
4  *
5  * Copyright (c) 2012-2021, Arm Limited.
6  */
7
8 /* Assumptions:
9  *
10  * ARMv8-a, AArch64, Advanced SIMD, unaligned accesses.
11  *
12  */
13
14 #include "asmdefs.h"
15
16 #define dstin   x0
17 #define val     x1
18 #define valw    w1
19 #define count   x2
20 #define dst     x3
21 #define dstend  x4
22 #define zva_val x5
23
24 ENTRY (memset)
25         PTR_ARG (0)
26         SIZE_ARG (2)
27
28         dup     v0.16B, valw
29         add     dstend, dstin, count
30
31         cmp     count, 96
32         b.hi    L(set_long)
33         cmp     count, 16
34         b.hs    L(set_medium)
35         mov     val, v0.D[0]
36
37         /* Set 0..15 bytes.  */
38         tbz     count, 3, 1f
39         str     val, [dstin]
40         str     val, [dstend, -8]
41         ret
42         .p2align 4
43 1:      tbz     count, 2, 2f
44         str     valw, [dstin]
45         str     valw, [dstend, -4]
46         ret
47 2:      cbz     count, 3f
48         strb    valw, [dstin]
49         tbz     count, 1, 3f
50         strh    valw, [dstend, -2]
51 3:      ret
52
53         /* Set 17..96 bytes.  */
54 L(set_medium):
55         str     q0, [dstin]
56         tbnz    count, 6, L(set96)
57         str     q0, [dstend, -16]
58         tbz     count, 5, 1f
59         str     q0, [dstin, 16]
60         str     q0, [dstend, -32]
61 1:      ret
62
63         .p2align 4
64         /* Set 64..96 bytes.  Write 64 bytes from the start and
65            32 bytes from the end.  */
66 L(set96):
67         str     q0, [dstin, 16]
68         stp     q0, q0, [dstin, 32]
69         stp     q0, q0, [dstend, -32]
70         ret
71
72         .p2align 4
73 L(set_long):
74         and     valw, valw, 255
75         bic     dst, dstin, 15
76         str     q0, [dstin]
77         cmp     count, 160
78         ccmp    valw, 0, 0, hs
79         b.ne    L(no_zva)
80
81 #ifndef SKIP_ZVA_CHECK
82         mrs     zva_val, dczid_el0
83         and     zva_val, zva_val, 31
84         cmp     zva_val, 4              /* ZVA size is 64 bytes.  */
85         b.ne    L(no_zva)
86 #endif
87         str     q0, [dst, 16]
88         stp     q0, q0, [dst, 32]
89         bic     dst, dst, 63
90         sub     count, dstend, dst      /* Count is now 64 too large.  */
91         sub     count, count, 128       /* Adjust count and bias for loop.  */
92
93         .p2align 4
94 L(zva_loop):
95         add     dst, dst, 64
96         dc      zva, dst
97         subs    count, count, 64
98         b.hi    L(zva_loop)
99         stp     q0, q0, [dstend, -64]
100         stp     q0, q0, [dstend, -32]
101         ret
102
103 L(no_zva):
104         sub     count, dstend, dst      /* Count is 16 too large.  */
105         sub     dst, dst, 16            /* Dst is biased by -32.  */
106         sub     count, count, 64 + 16   /* Adjust count and bias for loop.  */
107 L(no_zva_loop):
108         stp     q0, q0, [dst, 32]
109         stp     q0, q0, [dst, 64]!
110         subs    count, count, 64
111         b.hi    L(no_zva_loop)
112         stp     q0, q0, [dstend, -64]
113         stp     q0, q0, [dstend, -32]
114         ret
115
116 END (memset)