Partial ILP32 support for aarch64.
[glibc.git] / sysdeps / aarch64 / memset.S
blob7bad29a702841b8c9750a7f2132e79f2e940f5f6
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         DELOUSE (0)
43         DELOUSE (2)
45         dup     v0.16B, valw
46         add     dstend, dstin, count
48         cmp     count, 96
49         b.hi    L(set_long)
50         cmp     count, 16
51         b.hs    L(set_medium)
52         mov     val, v0.D[0]
54         /* Set 0..15 bytes.  */
55         tbz     count, 3, 1f
56         str     val, [dstin]
57         str     val, [dstend, -8]
58         ret
59         nop
60 1:      tbz     count, 2, 2f
61         str     valw, [dstin]
62         str     valw, [dstend, -4]
63         ret
64 2:      cbz     count, 3f
65         strb    valw, [dstin]
66         tbz     count, 1, 3f
67         strh    valw, [dstend, -2]
68 3:      ret
70         /* Set 17..96 bytes.  */
71 L(set_medium):
72         str     q0, [dstin]
73         tbnz    count, 6, L(set96)
74         str     q0, [dstend, -16]
75         tbz     count, 5, 1f
76         str     q0, [dstin, 16]
77         str     q0, [dstend, -32]
78 1:      ret
80         .p2align 4
81         /* Set 64..96 bytes.  Write 64 bytes from the start and
82            32 bytes from the end.  */
83 L(set96):
84         str     q0, [dstin, 16]
85         stp     q0, q0, [dstin, 32]
86         stp     q0, q0, [dstend, -32]
87         ret
89         .p2align 3
90         nop
91 L(set_long):
92         and     valw, valw, 255
93         bic     dst, dstin, 15
94         str     q0, [dstin]
95         cmp     count, 256
96         ccmp    valw, 0, 0, cs
97         b.eq    L(try_zva)
98 L(no_zva):
99         sub     count, dstend, dst      /* Count is 16 too large.  */
100         add     dst, dst, 16
101         sub     count, count, 64 + 16   /* Adjust count and bias for loop.  */
102 1:      stp     q0, q0, [dst], 64
103         stp     q0, q0, [dst, -32]
104 L(tail64):
105         subs    count, count, 64
106         b.hi    1b
107 2:      stp     q0, q0, [dstend, -64]
108         stp     q0, q0, [dstend, -32]
109         ret
111         .p2align 3
112 L(try_zva):
113         mrs     tmp1, dczid_el0
114         tbnz    tmp1w, 4, L(no_zva)
115         and     tmp1w, tmp1w, 15
116         cmp     tmp1w, 4        /* ZVA size is 64 bytes.  */
117         b.ne     L(zva_128)
119         /* Write the first and last 64 byte aligned block using stp rather
120            than using DC ZVA.  This is faster on some cores.
121          */
122 L(zva_64):
123         str     q0, [dst, 16]
124         stp     q0, q0, [dst, 32]
125         bic     dst, dst, 63
126         stp     q0, q0, [dst, 64]
127         stp     q0, q0, [dst, 96]
128         sub     count, dstend, dst      /* Count is now 128 too large.  */
129         sub     count, count, 128+64+64 /* Adjust count and bias for loop.  */
130         add     dst, dst, 128
131         nop
132 1:      dc      zva, dst
133         add     dst, dst, 64
134         subs    count, count, 64
135         b.hi    1b
136         stp     q0, q0, [dst, 0]
137         stp     q0, q0, [dst, 32]
138         stp     q0, q0, [dstend, -64]
139         stp     q0, q0, [dstend, -32]
140         ret
142         .p2align 3
143 L(zva_128):
144         cmp     tmp1w, 5        /* ZVA size is 128 bytes.  */
145         b.ne    L(zva_other)
147         str     q0, [dst, 16]
148         stp     q0, q0, [dst, 32]
149         stp     q0, q0, [dst, 64]
150         stp     q0, q0, [dst, 96]
151         bic     dst, dst, 127
152         sub     count, dstend, dst      /* Count is now 128 too large.  */
153         sub     count, count, 128+128   /* Adjust count and bias for loop.  */
154         add     dst, dst, 128
155 1:      dc      zva, dst
156         add     dst, dst, 128
157         subs    count, count, 128
158         b.hi    1b
159         stp     q0, q0, [dstend, -128]
160         stp     q0, q0, [dstend, -96]
161         stp     q0, q0, [dstend, -64]
162         stp     q0, q0, [dstend, -32]
163         ret
165 L(zva_other):
166         mov     tmp2w, 4
167         lsl     zva_lenw, tmp2w, tmp1w
168         add     tmp1, zva_len, 64       /* Max alignment bytes written.  */
169         cmp     count, tmp1
170         blo     L(no_zva)
172         sub     tmp2, zva_len, 1
173         add     tmp1, dst, zva_len
174         add     dst, dst, 16
175         subs    count, tmp1, dst        /* Actual alignment bytes to write.  */
176         bic     tmp1, tmp1, tmp2        /* Aligned dc zva start address.  */
177         beq     2f
178 1:      stp     q0, q0, [dst], 64
179         stp     q0, q0, [dst, -32]
180         subs    count, count, 64
181         b.hi    1b
182 2:      mov     dst, tmp1
183         sub     count, dstend, tmp1     /* Remaining bytes to write.  */
184         subs    count, count, zva_len
185         b.lo    4f
186 3:      dc      zva, dst
187         add     dst, dst, zva_len
188         subs    count, count, zva_len
189         b.hs    3b
190 4:      add     count, count, zva_len
191         b       L(tail64)
193 END (__memset)
194 weak_alias (__memset, memset)
195 libc_hidden_builtin_def (memset)