More NEWS entries / fixes for float_t / double_t changes.
[glibc.git] / sysdeps / aarch64 / memset.S
blob4d222c50aed3ca1be140bec8aa39acb47e410a4e
1 /* Copyright (C) 2012-2016 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library.  If not, see
17    <http://www.gnu.org/licenses/>.  */
19 #include <sysdep.h>
21 /* Assumptions:
22  *
23  * ARMv8-a, AArch64, unaligned accesses
24  *
25  */
27 #define dstin   x0
28 #define val     x1
29 #define valw    w1
30 #define count   x2
31 #define dst     x3
32 #define dstend  x4
33 #define tmp1    x5
34 #define tmp1w   w5
35 #define tmp2    x6
36 #define tmp2w   w6
37 #define zva_len x7
38 #define zva_lenw w7
40 ENTRY_ALIGN (__memset, 6)
42         dup     v0.16B, valw
43         add     dstend, dstin, count
45         cmp     count, 96
46         b.hi    L(set_long)
47         cmp     count, 16
48         b.hs    L(set_medium)
49         mov     val, v0.D[0]
51         /* Set 0..15 bytes.  */
52         tbz     count, 3, 1f
53         str     val, [dstin]
54         str     val, [dstend, -8]
55         ret
56         nop
57 1:      tbz     count, 2, 2f
58         str     valw, [dstin]
59         str     valw, [dstend, -4]
60         ret
61 2:      cbz     count, 3f
62         strb    valw, [dstin]
63         tbz     count, 1, 3f
64         strh    valw, [dstend, -2]
65 3:      ret
67         /* Set 17..96 bytes.  */
68 L(set_medium):
69         str     q0, [dstin]
70         tbnz    count, 6, L(set96)
71         str     q0, [dstend, -16]
72         tbz     count, 5, 1f
73         str     q0, [dstin, 16]
74         str     q0, [dstend, -32]
75 1:      ret
77         .p2align 4
78         /* Set 64..96 bytes.  Write 64 bytes from the start and
79            32 bytes from the end.  */
80 L(set96):
81         str     q0, [dstin, 16]
82         stp     q0, q0, [dstin, 32]
83         stp     q0, q0, [dstend, -32]
84         ret
86         .p2align 3
87         nop
88 L(set_long):
89         and     valw, valw, 255
90         bic     dst, dstin, 15
91         str     q0, [dstin]
92         cmp     count, 256
93         ccmp    valw, 0, 0, cs
94         b.eq    L(try_zva)
95 L(no_zva):
96         sub     count, dstend, dst      /* Count is 16 too large.  */
97         add     dst, dst, 16
98         sub     count, count, 64 + 16   /* Adjust count and bias for loop.  */
99 1:      stp     q0, q0, [dst], 64
100         stp     q0, q0, [dst, -32]
101 L(tail64):
102         subs    count, count, 64
103         b.hi    1b
104 2:      stp     q0, q0, [dstend, -64]
105         stp     q0, q0, [dstend, -32]
106         ret
108         .p2align 3
109 L(try_zva):
110         mrs     tmp1, dczid_el0
111         tbnz    tmp1w, 4, L(no_zva)
112         and     tmp1w, tmp1w, 15
113         cmp     tmp1w, 4        /* ZVA size is 64 bytes.  */
114         b.ne     L(zva_128)
116         /* Write the first and last 64 byte aligned block using stp rather
117            than using DC ZVA.  This is faster on some cores.
118          */
119 L(zva_64):
120         str     q0, [dst, 16]
121         stp     q0, q0, [dst, 32]
122         bic     dst, dst, 63
123         stp     q0, q0, [dst, 64]
124         stp     q0, q0, [dst, 96]
125         sub     count, dstend, dst      /* Count is now 128 too large.  */
126         sub     count, count, 128+64+64 /* Adjust count and bias for loop.  */
127         add     dst, dst, 128
128         nop
129 1:      dc      zva, dst
130         add     dst, dst, 64
131         subs    count, count, 64
132         b.hi    1b
133         stp     q0, q0, [dst, 0]
134         stp     q0, q0, [dst, 32]
135         stp     q0, q0, [dstend, -64]
136         stp     q0, q0, [dstend, -32]
137         ret
139         .p2align 3
140 L(zva_128):
141         cmp     tmp1w, 5        /* ZVA size is 128 bytes.  */
142         b.ne    L(zva_other)
144         str     q0, [dst, 16]
145         stp     q0, q0, [dst, 32]
146         stp     q0, q0, [dst, 64]
147         stp     q0, q0, [dst, 96]
148         bic     dst, dst, 127
149         sub     count, dstend, dst      /* Count is now 128 too large.  */
150         sub     count, count, 128+128   /* Adjust count and bias for loop.  */
151         add     dst, dst, 128
152 1:      dc      zva, dst
153         add     dst, dst, 128
154         subs    count, count, 128
155         b.hi    1b
156         stp     q0, q0, [dstend, -128]
157         stp     q0, q0, [dstend, -96]
158         stp     q0, q0, [dstend, -64]
159         stp     q0, q0, [dstend, -32]
160         ret
162 L(zva_other):
163         mov     tmp2w, 4
164         lsl     zva_lenw, tmp2w, tmp1w
165         add     tmp1, zva_len, 64       /* Max alignment bytes written.  */
166         cmp     count, tmp1
167         blo     L(no_zva)
169         sub     tmp2, zva_len, 1
170         add     tmp1, dst, zva_len
171         add     dst, dst, 16
172         subs    count, tmp1, dst        /* Actual alignment bytes to write.  */
173         bic     tmp1, tmp1, tmp2        /* Aligned dc zva start address.  */
174         beq     2f
175 1:      stp     q0, q0, [dst], 64
176         stp     q0, q0, [dst, -32]
177         subs    count, count, 64
178         b.hi    1b
179 2:      mov     dst, tmp1
180         sub     count, dstend, tmp1     /* Remaining bytes to write.  */
181         subs    count, count, zva_len
182         b.lo    4f
183 3:      dc      zva, dst
184         add     dst, dst, zva_len
185         subs    count, count, zva_len
186         b.hs    3b
187 4:      add     count, count, zva_len
188         b       L(tail64)
190 END (__memset)
191 weak_alias (__memset, memset)
192 libc_hidden_builtin_def (memset)