aarch64: Fix assembling chacha20-aarch64.S with clang/llvm
[libgcrypt.git] / cipher / chacha20-aarch64.S
1 /* chacha20-aarch64.S - ARMv8/AArch64 accelerated chacha20 blocks function
2  *
3  * Copyright (C) 2017,2018 Jussi Kivilinna <jussi.kivilinna@iki.fi>
4  *
5  * This file is part of Libgcrypt.
6  *
7  * Libgcrypt is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU Lesser General Public License as
9  * published by the Free Software Foundation; either version 2.1 of
10  * the License, or (at your option) any later version.
11  *
12  * Libgcrypt is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this program; if not, see <http://www.gnu.org/licenses/>.
19  */
20
21 /*
22  * Based on D. J. Bernstein reference implementation at
23  * http://cr.yp.to/chacha.html:
24  *
25  * chacha-regs.c version 20080118
26  * D. J. Bernstein
27  * Public domain.
28  */
29
30 #include <config.h>
31
32 #if defined(__AARCH64EL__) && \
33     defined(HAVE_COMPATIBLE_GCC_AARCH64_PLATFORM_AS) && \
34     defined(HAVE_GCC_INLINE_ASM_AARCH64_NEON) && \
35     defined(USE_CHACHA20)
36
37 .cpu generic+simd
38
39 .text
40
41 #define GET_DATA_POINTER(reg, name) \
42         adrp    reg, :got:name ; \
43         ldr     reg, [reg, #:got_lo12:name] ;
44
45 /* register macros */
46 #define INPUT     x0
47 #define DST       x1
48 #define SRC       x2
49 #define NBLKS     x3
50 #define ROUND     x4
51 #define INPUT_CTR x5
52 #define INPUT_POS x6
53 #define CTR       x7
54
55 /* vector registers */
56 #define X0 v16
57 #define X1 v17
58 #define X2 v18
59 #define X3 v19
60 #define X4 v20
61 #define X5 v21
62 #define X6 v22
63 #define X7 v23
64 #define X8 v24
65 #define X9 v25
66 #define X10 v26
67 #define X11 v27
68 #define X12 v28
69 #define X13 v29
70 #define X14 v30
71 #define X15 v31
72
73 #define VCTR    v0
74 #define VTMP0   v1
75 #define VTMP1   v2
76 #define VTMP2   v3
77 #define VTMP3   v4
78 #define X12_TMP v5
79 #define X13_TMP v6
80
81 /**********************************************************************
82   helper macros
83  **********************************************************************/
84
85 #define vpunpckldq(s1, s2, dst) \
86         zip1 dst.4s, s2.4s, s1.4s;
87
88 #define vpunpckhdq(s1, s2, dst) \
89         zip2 dst.4s, s2.4s, s1.4s;
90
91 #define vpunpcklqdq(s1, s2, dst) \
92         zip1 dst.2d, s2.2d, s1.2d;
93
94 #define vpunpckhqdq(s1, s2, dst) \
95         zip2 dst.2d, s2.2d, s1.2d;
96
97 /* 4x4 32-bit integer matrix transpose */
98 #define transpose_4x4(x0, x1, x2, x3, t1, t2, t3) \
99         vpunpckhdq(x1, x0, t2); \
100         vpunpckldq(x1, x0, x0); \
101         \
102         vpunpckldq(x3, x2, t1); \
103         vpunpckhdq(x3, x2, x2); \
104         \
105         vpunpckhqdq(t1, x0, x1); \
106         vpunpcklqdq(t1, x0, x0); \
107         \
108         vpunpckhqdq(x2, t2, x3); \
109         vpunpcklqdq(x2, t2, x2);
110
111 #define clear(x) \
112         eor x.16b, x.16b, x.16b;
113
114 /**********************************************************************
115   4-way chacha20
116  **********************************************************************/
117
118 #define ROTATE2(dst1,dst2,c,src1,src2)          \
119         shl dst1.4s, src1.4s, #(c);             \
120         shl dst2.4s, src2.4s, #(c);             \
121         sri dst1.4s, src1.4s, #(32 - (c));      \
122         sri dst2.4s, src2.4s, #(32 - (c));
123
124 #define ROTATE2_16(dst1,dst2,src1,src2)         \
125         rev32 dst1.8h, src1.8h;                 \
126         rev32 dst2.8h, src2.8h;
127
128 #define XOR(d,s1,s2) \
129         eor d.16b, s2.16b, s1.16b;
130
131 #define PLUS(ds,s) \
132         add ds.4s, ds.4s, s.4s;
133
134 #define QUARTERROUND2(a1,b1,c1,d1,a2,b2,c2,d2,ign,tmp1,tmp2)            \
135         PLUS(a1,b1); PLUS(a2,b2); XOR(tmp1,d1,a1); XOR(tmp2,d2,a2);     \
136             ROTATE2_16(d1, d2, tmp1, tmp2);                             \
137         PLUS(c1,d1); PLUS(c2,d2); XOR(tmp1,b1,c1); XOR(tmp2,b2,c2);     \
138             ROTATE2(b1, b2, 12, tmp1, tmp2);                            \
139         PLUS(a1,b1); PLUS(a2,b2); XOR(tmp1,d1,a1); XOR(tmp2,d2,a2);     \
140             ROTATE2(d1, d2,  8, tmp1, tmp2);                            \
141         PLUS(c1,d1); PLUS(c2,d2); XOR(tmp1,b1,c1); XOR(tmp2,b2,c2);     \
142             ROTATE2(b1, b2,  7, tmp1, tmp2);
143
144 chacha20_data:
145 .align 4
146 .Linc_counter:
147         .long 0,1,2,3
148
149 .align 3
150 .globl _gcry_chacha20_aarch64_blocks4
151 .type _gcry_chacha20_aarch64_blocks4,%function;
152
153 _gcry_chacha20_aarch64_blocks4:
154         /* input:
155          *      x0: input
156          *      x1: dst
157          *      x2: src
158          *      x3: nblks (multiple of 4)
159          */
160
161         GET_DATA_POINTER(CTR, .Linc_counter);
162         add INPUT_CTR, INPUT, #(12*4);
163         mov INPUT_POS, INPUT;
164         ld1 {VCTR.16b}, [CTR];
165
166 .Loop4:
167         /* Construct counter vectors X12 and X13 */
168
169         ld1 {X15.16b}, [INPUT_CTR];
170         mov ROUND, #20;
171         ld1 {VTMP1.16b-VTMP3.16b}, [INPUT_POS];
172
173         dup X12.4s, X15.s[0];
174         dup X13.4s, X15.s[1];
175         ldr CTR, [INPUT_CTR];
176         add X12.4s, X12.4s, VCTR.4s;
177         dup X0.4s, VTMP1.s[0];
178         dup X1.4s, VTMP1.s[1];
179         dup X2.4s, VTMP1.s[2];
180         dup X3.4s, VTMP1.s[3];
181         dup X14.4s, X15.s[2];
182         cmhi VTMP0.4s, VCTR.4s, X12.4s;
183         dup X15.4s, X15.s[3];
184         add CTR, CTR, #4; /* Update counter */
185         dup X4.4s, VTMP2.s[0];
186         dup X5.4s, VTMP2.s[1];
187         dup X6.4s, VTMP2.s[2];
188         dup X7.4s, VTMP2.s[3];
189         sub X13.4s, X13.4s, VTMP0.4s;
190         dup X8.4s, VTMP3.s[0];
191         dup X9.4s, VTMP3.s[1];
192         dup X10.4s, VTMP3.s[2];
193         dup X11.4s, VTMP3.s[3];
194         mov X12_TMP.16b, X12.16b;
195         mov X13_TMP.16b, X13.16b;
196         str CTR, [INPUT_CTR];
197
198 .Lround2:
199         subs ROUND, ROUND, #2
200         QUARTERROUND2(X0, X4,  X8, X12,   X1, X5,  X9, X13, tmp:=,VTMP0,VTMP1)
201         QUARTERROUND2(X2, X6, X10, X14,   X3, X7, X11, X15, tmp:=,VTMP0,VTMP1)
202         QUARTERROUND2(X0, X5, X10, X15,   X1, X6, X11, X12, tmp:=,VTMP0,VTMP1)
203         QUARTERROUND2(X2, X7,  X8, X13,   X3, X4,  X9, X14, tmp:=,VTMP0,VTMP1)
204         b.ne .Lround2;
205
206         ld1 {VTMP0.16b, VTMP1.16b}, [INPUT_POS], #32;
207
208         PLUS(X12, X12_TMP);        /* INPUT + 12 * 4 + counter */
209         PLUS(X13, X13_TMP);        /* INPUT + 13 * 4 + counter */
210
211         dup VTMP2.4s, VTMP0.s[0]; /* INPUT + 0 * 4 */
212         dup VTMP3.4s, VTMP0.s[1]; /* INPUT + 1 * 4 */
213         dup X12_TMP.4s, VTMP0.s[2]; /* INPUT + 2 * 4 */
214         dup X13_TMP.4s, VTMP0.s[3]; /* INPUT + 3 * 4 */
215         PLUS(X0, VTMP2);
216         PLUS(X1, VTMP3);
217         PLUS(X2, X12_TMP);
218         PLUS(X3, X13_TMP);
219
220         dup VTMP2.4s, VTMP1.s[0]; /* INPUT + 4 * 4 */
221         dup VTMP3.4s, VTMP1.s[1]; /* INPUT + 5 * 4 */
222         dup X12_TMP.4s, VTMP1.s[2]; /* INPUT + 6 * 4 */
223         dup X13_TMP.4s, VTMP1.s[3]; /* INPUT + 7 * 4 */
224         ld1 {VTMP0.16b, VTMP1.16b}, [INPUT_POS];
225         mov INPUT_POS, INPUT;
226         PLUS(X4, VTMP2);
227         PLUS(X5, VTMP3);
228         PLUS(X6, X12_TMP);
229         PLUS(X7, X13_TMP);
230
231         dup VTMP2.4s, VTMP0.s[0]; /* INPUT + 8 * 4 */
232         dup VTMP3.4s, VTMP0.s[1]; /* INPUT + 9 * 4 */
233         dup X12_TMP.4s, VTMP0.s[2]; /* INPUT + 10 * 4 */
234         dup X13_TMP.4s, VTMP0.s[3]; /* INPUT + 11 * 4 */
235         dup VTMP0.4s, VTMP1.s[2]; /* INPUT + 14 * 4 */
236         dup VTMP1.4s, VTMP1.s[3]; /* INPUT + 15 * 4 */
237         PLUS(X8, VTMP2);
238         PLUS(X9, VTMP3);
239         PLUS(X10, X12_TMP);
240         PLUS(X11, X13_TMP);
241         PLUS(X14, VTMP0);
242         PLUS(X15, VTMP1);
243
244         transpose_4x4(X0, X1, X2, X3, VTMP0, VTMP1, VTMP2);
245         transpose_4x4(X4, X5, X6, X7, VTMP0, VTMP1, VTMP2);
246         transpose_4x4(X8, X9, X10, X11, VTMP0, VTMP1, VTMP2);
247         transpose_4x4(X12, X13, X14, X15, VTMP0, VTMP1, VTMP2);
248
249         subs NBLKS, NBLKS, #4;
250
251         ld1 {VTMP0.16b-VTMP3.16b}, [SRC], #64;
252         ld1 {X12_TMP.16b-X13_TMP.16b}, [SRC], #32;
253         eor VTMP0.16b, X0.16b, VTMP0.16b;
254         eor VTMP1.16b, X4.16b, VTMP1.16b;
255         eor VTMP2.16b, X8.16b, VTMP2.16b;
256         eor VTMP3.16b, X12.16b, VTMP3.16b;
257         eor X12_TMP.16b, X1.16b, X12_TMP.16b;
258         eor X13_TMP.16b, X5.16b, X13_TMP.16b;
259         st1 {VTMP0.16b-VTMP3.16b}, [DST], #64;
260         ld1 {VTMP0.16b-VTMP3.16b}, [SRC], #64;
261         st1 {X12_TMP.16b-X13_TMP.16b}, [DST], #32;
262         ld1 {X12_TMP.16b-X13_TMP.16b}, [SRC], #32;
263         eor VTMP0.16b, X9.16b, VTMP0.16b;
264         eor VTMP1.16b, X13.16b, VTMP1.16b;
265         eor VTMP2.16b, X2.16b, VTMP2.16b;
266         eor VTMP3.16b, X6.16b, VTMP3.16b;
267         eor X12_TMP.16b, X10.16b, X12_TMP.16b;
268         eor X13_TMP.16b, X14.16b, X13_TMP.16b;
269         st1 {VTMP0.16b-VTMP3.16b}, [DST], #64;
270         ld1 {VTMP0.16b-VTMP3.16b}, [SRC], #64;
271         st1 {X12_TMP.16b-X13_TMP.16b}, [DST], #32;
272         eor VTMP0.16b, X3.16b, VTMP0.16b;
273         eor VTMP1.16b, X7.16b, VTMP1.16b;
274         eor VTMP2.16b, X11.16b, VTMP2.16b;
275         eor VTMP3.16b, X15.16b, VTMP3.16b;
276         st1 {VTMP0.16b-VTMP3.16b}, [DST], #64;
277
278         b.ne .Loop4;
279
280         /* clear the used vector registers and stack */
281         clear(VTMP0);
282         clear(VTMP1);
283         clear(VTMP2);
284         clear(VTMP3);
285         clear(X12_TMP);
286         clear(X13_TMP);
287         clear(X0);
288         clear(X1);
289         clear(X2);
290         clear(X3);
291         clear(X4);
292         clear(X5);
293         clear(X6);
294         clear(X7);
295         clear(X8);
296         clear(X9);
297         clear(X10);
298         clear(X11);
299         clear(X12);
300         clear(X13);
301         clear(X14);
302         clear(X15);
303
304         eor x0, x0, x0
305         ret
306 .size _gcry_chacha20_aarch64_blocks4, .-_gcry_chacha20_aarch64_blocks4;
307
308 #endif