chacha_neon_32.S revision 1.2 1 1.2 riastrad /* $NetBSD: chacha_neon_32.S,v 1.2 2020/07/29 14:23:59 riastradh Exp $ */
2 1.1 riastrad
3 1.1 riastrad /*-
4 1.1 riastrad * Copyright (c) 2020 The NetBSD Foundation, Inc.
5 1.1 riastrad * All rights reserved.
6 1.1 riastrad *
7 1.1 riastrad * Redistribution and use in source and binary forms, with or without
8 1.1 riastrad * modification, are permitted provided that the following conditions
9 1.1 riastrad * are met:
10 1.1 riastrad * 1. Redistributions of source code must retain the above copyright
11 1.1 riastrad * notice, this list of conditions and the following disclaimer.
12 1.1 riastrad * 2. Redistributions in binary form must reproduce the above copyright
13 1.1 riastrad * notice, this list of conditions and the following disclaimer in the
14 1.1 riastrad * documentation and/or other materials provided with the distribution.
15 1.1 riastrad *
16 1.1 riastrad * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17 1.1 riastrad * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18 1.1 riastrad * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 1.1 riastrad * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20 1.1 riastrad * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 1.1 riastrad * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 1.1 riastrad * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 1.1 riastrad * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 1.1 riastrad * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 1.1 riastrad * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 1.1 riastrad * POSSIBILITY OF SUCH DAMAGE.
27 1.1 riastrad */
28 1.1 riastrad
29 1.1 riastrad #include <machine/asm.h>
30 1.1 riastrad
31 1.2 riastrad RCSID("$NetBSD: chacha_neon_32.S,v 1.2 2020/07/29 14:23:59 riastradh Exp $")
32 1.1 riastrad
33 1.1 riastrad .fpu neon
34 1.1 riastrad
35 1.1 riastrad /*
36 1.1 riastrad * ChaCha round, split up so we can interleave the quarterrounds on
37 1.1 riastrad * independent rows/diagonals to maximize pipeline efficiency, with
38 1.1 riastrad * spills to deal with the scarcity of registers. Reference:
39 1.1 riastrad *
40 1.1 riastrad * Daniel J. Bernstein, `ChaCha, a variant of Salsa20', Workshop
41 1.1 riastrad * Record of the State of the Art in Stream Ciphers -- SASC 2008.
42 1.1 riastrad * https://cr.yp.to/papers.html#chacha
43 1.1 riastrad *
44 1.1 riastrad * a += b; d ^= a; d <<<= 16;
45 1.1 riastrad * c += d; b ^= c; b <<<= 12;
46 1.1 riastrad * a += b; d ^= a; d <<<= 8;
47 1.1 riastrad * c += d; b ^= c; b <<<= 7;
48 1.1 riastrad *
49 1.1 riastrad * The rotations are implemented with:
50 1.1 riastrad * <<< 16 VREV32.16 for 16,
51 1.1 riastrad * <<< 12 VSHL/VSRI/VORR (shift left, shift right and insert, OR)
52 1.1 riastrad * <<< 8 TBL (general permutation; rot8 below stored in r)
53 1.1 riastrad * <<< 7 VSHL/VSRI/VORR
54 1.1 riastrad */
55 1.1 riastrad
56 1.1 riastrad .macro ROUNDLD a0,a1,a2,a3, b0,b1,b2,b3, c0,c1,c2,c3, d0,d1,d2,d3
57 1.1 riastrad vld1.32 {\c2-\c3}, [fp, :256]
58 1.1 riastrad .endm
59 1.1 riastrad
60 1.1 riastrad .macro ROUND a0,a1,a2,a3, b0,b1,b2,b3, c0,c1,c2,c3, d0,d1,d2,d3, c0l, d0l,d0h,d1l,d1h,d2l,d2h,d3l,d3h
61 1.1 riastrad /* a += b; d ^= a; d <<<= 16 */
62 1.1 riastrad vadd.u32 \a0, \a0, \b0
63 1.1 riastrad vadd.u32 \a1, \a1, \b1
64 1.1 riastrad vadd.u32 \a2, \a2, \b2
65 1.1 riastrad vadd.u32 \a3, \a3, \b3
66 1.1 riastrad
67 1.1 riastrad veor \d0, \d0, \a0
68 1.1 riastrad veor \d1, \d1, \a1
69 1.1 riastrad veor \d2, \d2, \a2
70 1.1 riastrad veor \d3, \d3, \a3
71 1.1 riastrad
72 1.1 riastrad vrev32.16 \d0, \d0
73 1.1 riastrad vrev32.16 \d1, \d1
74 1.1 riastrad vrev32.16 \d2, \d2
75 1.1 riastrad vrev32.16 \d3, \d3
76 1.1 riastrad
77 1.1 riastrad /* c += d; b ^= c; b <<<= 12 */
78 1.1 riastrad vadd.u32 \c0, \c0, \d0
79 1.1 riastrad vadd.u32 \c1, \c1, \d1
80 1.1 riastrad vadd.u32 \c2, \c2, \d2
81 1.1 riastrad vadd.u32 \c3, \c3, \d3
82 1.1 riastrad
83 1.1 riastrad vst1.32 {\c0-\c1}, [fp, :256] /* free c0 and c1 as temps */
84 1.1 riastrad
85 1.1 riastrad veor \c0, \b0, \c0
86 1.1 riastrad veor \c1, \b1, \c1
87 1.1 riastrad vshl.u32 \b0, \c0, #12
88 1.1 riastrad vshl.u32 \b1, \c1, #12
89 1.1 riastrad vsri.u32 \b0, \c0, #(32 - 12)
90 1.1 riastrad vsri.u32 \b1, \c1, #(32 - 12)
91 1.1 riastrad
92 1.1 riastrad veor \c0, \b2, \c2
93 1.1 riastrad veor \c1, \b3, \c3
94 1.1 riastrad vshl.u32 \b2, \c0, #12
95 1.1 riastrad vshl.u32 \b3, \c1, #12
96 1.1 riastrad vsri.u32 \b2, \c0, #(32 - 12)
97 1.1 riastrad vsri.u32 \b3, \c1, #(32 - 12)
98 1.1 riastrad
99 1.1 riastrad vld1.8 {\c0l}, [r7, :64] /* load rot8 table */
100 1.1 riastrad
101 1.1 riastrad /* a += b; d ^= a; d <<<= 8 */
102 1.1 riastrad vadd.u32 \a0, \a0, \b0
103 1.1 riastrad vadd.u32 \a1, \a1, \b1
104 1.1 riastrad vadd.u32 \a2, \a2, \b2
105 1.1 riastrad vadd.u32 \a3, \a3, \b3
106 1.1 riastrad
107 1.1 riastrad veor \d0, \d0, \a0
108 1.1 riastrad veor \d1, \d1, \a1
109 1.1 riastrad veor \d2, \d2, \a2
110 1.1 riastrad veor \d3, \d3, \a3
111 1.1 riastrad
112 1.1 riastrad vtbl.8 \d0l, {\d0l}, \c0l /* <<< 8 */
113 1.1 riastrad vtbl.8 \d0h, {\d0h}, \c0l
114 1.1 riastrad vtbl.8 \d1l, {\d1l}, \c0l
115 1.1 riastrad vtbl.8 \d1h, {\d1h}, \c0l
116 1.1 riastrad vtbl.8 \d2l, {\d2l}, \c0l
117 1.1 riastrad vtbl.8 \d2h, {\d2h}, \c0l
118 1.1 riastrad vtbl.8 \d3l, {\d3l}, \c0l
119 1.1 riastrad vtbl.8 \d3h, {\d3h}, \c0l
120 1.1 riastrad
121 1.1 riastrad vld1.32 {\c0-\c1}, [fp, :256] /* restore c0 and c1 */
122 1.1 riastrad
123 1.1 riastrad /* c += d; b ^= c; b <<<= 7 */
124 1.1 riastrad vadd.u32 \c2, \c2, \d2
125 1.1 riastrad vadd.u32 \c3, \c3, \d3
126 1.1 riastrad vadd.u32 \c0, \c0, \d0
127 1.1 riastrad vadd.u32 \c1, \c1, \d1
128 1.1 riastrad
129 1.1 riastrad vst1.32 {\c2-\c3}, [fp, :256] /* free c2 and c3 as temps */
130 1.1 riastrad
131 1.1 riastrad veor \c2, \b2, \c2
132 1.1 riastrad veor \c3, \b3, \c3
133 1.1 riastrad vshl.u32 \b2, \c2, #7
134 1.1 riastrad vshl.u32 \b3, \c3, #7
135 1.1 riastrad vsri.u32 \b2, \c2, #(32 - 7)
136 1.1 riastrad vsri.u32 \b3, \c3, #(32 - 7)
137 1.1 riastrad
138 1.1 riastrad veor \c2, \b0, \c0
139 1.1 riastrad veor \c3, \b1, \c1
140 1.1 riastrad vshl.u32 \b0, \c2, #7
141 1.1 riastrad vshl.u32 \b1, \c3, #7
142 1.1 riastrad vsri.u32 \b0, \c2, #(32 - 7)
143 1.1 riastrad vsri.u32 \b1, \c3, #(32 - 7)
144 1.1 riastrad .endm
145 1.1 riastrad
146 1.1 riastrad #if _BYTE_ORDER == _LITTLE_ENDIAN
147 1.1 riastrad #define HTOLE32(x)
148 1.1 riastrad #define LE32TOH(x)
149 1.1 riastrad #elif _BYTE_ORDER == _BIG_ENDIAN
150 1.1 riastrad #define HTOLE32(x) vrev32.8 x, x
151 1.1 riastrad #define LE32TOH(x) vrev32.8 x, x
152 1.1 riastrad #endif
153 1.1 riastrad
154 1.1 riastrad .text
155 1.1 riastrad .p2align 2
156 1.1 riastrad .Lconstants_addr:
157 1.1 riastrad .long .Lconstants - .
158 1.1 riastrad
159 1.1 riastrad /*
160 1.1 riastrad * chacha_stream256_neon(uint8_t s[256]@r0,
161 1.1 riastrad * uint32_t blkno@r1,
162 1.1 riastrad * const uint8_t nonce[12]@r2,
163 1.1 riastrad * const uint8_t key[32]@r3,
164 1.1 riastrad * const uint8_t const[16]@sp[0],
165 1.1 riastrad * unsigned nr@sp[4])
166 1.1 riastrad */
167 1.1 riastrad ENTRY(chacha_stream256_neon)
168 1.1 riastrad /* save callee-saves registers */
169 1.1 riastrad push {r4, r5, r6, r7, r8, r10, fp, lr}
170 1.1 riastrad vpush {d8-d15}
171 1.1 riastrad
172 1.1 riastrad /* r7 := .Lconstants - .Lconstants_addr, r6 := .Lconstants_addr */
173 1.1 riastrad ldr r7, .Lconstants_addr
174 1.1 riastrad adr r6, .Lconstants_addr
175 1.1 riastrad
176 1.1 riastrad /* reserve space for two 128-bit/16-byte q registers */
177 1.1 riastrad sub fp, sp, #0x20
178 1.1 riastrad bic fp, fp, #0x1f /* align */
179 1.1 riastrad
180 1.1 riastrad /* get parameters */
181 1.1 riastrad add ip, sp, #96
182 1.1 riastrad add r7, r7, r6 /* r7 := .Lconstants (= v0123) */
183 1.1 riastrad ldm ip, {r4, r5} /* r4 := const, r5 := nr */
184 1.1 riastrad ldm r2, {r6, r8, r10} /* (r6, r8, r10) := nonce[0:12) */
185 1.1 riastrad
186 1.1 riastrad vld1.32 {q12}, [r4] /* q12 := constant */
187 1.1 riastrad vld1.32 {q13-q14}, [r3] /* q13-q14 := key */
188 1.1 riastrad vld1.32 {q15}, [r7, :128]! /* q15 := (0, 1, 2, 3) (128-bit aligned) */
189 1.1 riastrad
190 1.1 riastrad vdup.32 q0, d24[0] /* q0-q3 := constant */
191 1.1 riastrad vdup.32 q1, d24[1]
192 1.1 riastrad vdup.32 q2, d25[0]
193 1.1 riastrad vdup.32 q3, d25[1]
194 1.1 riastrad vdup.32 q12, r1 /* q12 := (blkno, blkno, blkno, blkno) */
195 1.1 riastrad vdup.32 q4, d26[0] /* q4-q11 := (key, key, key, key) */
196 1.1 riastrad vdup.32 q5, d26[1]
197 1.1 riastrad vdup.32 q6, d27[0]
198 1.1 riastrad vdup.32 q7, d27[1]
199 1.1 riastrad vdup.32 q8, d28[0]
200 1.1 riastrad vdup.32 q9, d28[1]
201 1.1 riastrad vdup.32 q10, d29[0]
202 1.1 riastrad vdup.32 q11, d29[1]
203 1.1 riastrad vadd.u32 q12, q12, q15 /* q12 := (blkno,blkno+1,blkno+2,blkno+3) */
204 1.1 riastrad vdup.32 q13, r6 /* q13-q15 := nonce */
205 1.1 riastrad vdup.32 q14, r8
206 1.1 riastrad vdup.32 q15, r10
207 1.1 riastrad
208 1.1 riastrad HTOLE32(q0)
209 1.1 riastrad HTOLE32(q1)
210 1.1 riastrad HTOLE32(q2)
211 1.1 riastrad HTOLE32(q3)
212 1.1 riastrad HTOLE32(q4)
213 1.1 riastrad HTOLE32(q5)
214 1.1 riastrad HTOLE32(q6)
215 1.1 riastrad HTOLE32(q7)
216 1.1 riastrad HTOLE32(q8)
217 1.1 riastrad HTOLE32(q9)
218 1.1 riastrad HTOLE32(q10)
219 1.1 riastrad HTOLE32(q11)
220 1.1 riastrad HTOLE32(q12)
221 1.1 riastrad HTOLE32(q13)
222 1.1 riastrad HTOLE32(q14)
223 1.1 riastrad HTOLE32(q15)
224 1.1 riastrad
225 1.1 riastrad b 2f
226 1.1 riastrad
227 1.1 riastrad _ALIGN_TEXT
228 1.1 riastrad 1: ROUNDLD q0,q1,q2,q3, q5,q6,q7,q4, q10,q11,q8,q9, q15,q12,q13,q14
229 1.1 riastrad 2: subs r5, r5, #2
230 1.1 riastrad ROUND q0,q1,q2,q3, q4,q5,q6,q7, q8,q9,q10,q11, q12,q13,q14,q15, \
231 1.1 riastrad d16, d24,d25, d26,d27, d28,d29, d30,d31
232 1.1 riastrad ROUNDLD q0,q1,q2,q3, q4,q5,q6,q7, q8,q9,q10,q11, q12,q13,q14,q15
233 1.1 riastrad ROUND q0,q1,q2,q3, q5,q6,q7,q4, q10,q11,q8,q9, q15,q12,q13,q14, \
234 1.1 riastrad d20, d30,d31, d24,d25, d26,d27, d28,d29
235 1.1 riastrad bne 1b
236 1.1 riastrad
237 1.1 riastrad /*
238 1.1 riastrad * q8-q9 are free / saved on the stack. We have:
239 1.1 riastrad *
240 1.1 riastrad * q0 = (x0[0], x1[0]; x2[0], x3[0])
241 1.1 riastrad * q1 = (x0[1], x1[1]; x2[1], x3[1])
242 1.1 riastrad * q2 = (x0[2], x1[2]; x2[2], x3[2])
243 1.1 riastrad * q3 = (x0[3], x1[3]; x2[3], x3[3])
244 1.1 riastrad * ...
245 1.1 riastrad * q15 = (x0[15], x1[15]; x2[15], x3[15])
246 1.1 riastrad *
247 1.1 riastrad * where xi[j] is the jth word of the ith 16-word block. Zip
248 1.1 riastrad * consecutive pairs with vzip.32, and you get:
249 1.1 riastrad *
250 1.1 riastrad * q0 = (x0[0], x0[1]; x1[0], x1[1])
251 1.1 riastrad * q1 = (x2[0], x2[1]; x3[0], x3[1])
252 1.1 riastrad * q2 = (x0[2], x0[3]; x1[2], x1[3])
253 1.1 riastrad * q3 = (x2[2], x2[3]; x3[2], x3[3])
254 1.1 riastrad * ...
255 1.1 riastrad * q15 = (x2[14], x2[15]; x3[14], x3[15])
256 1.1 riastrad *
257 1.1 riastrad * As 64-bit d registers, this is:
258 1.1 riastrad *
259 1.1 riastrad * d0 = (x0[0], x0[1]) d1 = (x1[0], x1[1])
260 1.1 riastrad * d2 = (x2[0], x2[1]) d3 = (x3[0], x3[1])
261 1.1 riastrad * d4 = (x0[2], x0[3]) d5 = (x1[2], x1[3])
262 1.1 riastrad * d6 = (x2[2], x2[3]) d7 = (x3[2], x3[3])
263 1.1 riastrad * ...
264 1.1 riastrad * d30 = (x2[14], x2[15]) d31 = (x3[14], x3[15])
265 1.1 riastrad *
266 1.1 riastrad * Swap d1<->d4, d3<->d6, ..., and you get:
267 1.1 riastrad *
268 1.1 riastrad * q0 = (x0[0], x0[1]; x0[2], x0[3])
269 1.1 riastrad * q1 = (x2[0], x2[1]; x2[2], x2[3])
270 1.1 riastrad * q2 = (x1[0], x1[1]; x1[2], x1[3])
271 1.1 riastrad * q3 = (x3[0], x3[1]; x3[2], x3[3])
272 1.1 riastrad * ...
273 1.1 riastrad * q15 = (x15[0], x15[1]; x15[2], x15[3])
274 1.1 riastrad */
275 1.1 riastrad
276 1.1 riastrad sub r7, r7, #0x10
277 1.1 riastrad vdup.32 q8, r1 /* q8 := (blkno, blkno, blkno, blkno) */
278 1.1 riastrad vld1.32 {q9}, [r7, :128] /* q9 := (0, 1, 2, 3) */
279 1.1 riastrad
280 1.1 riastrad vzip.32 q0, q1
281 1.1 riastrad vzip.32 q2, q3
282 1.1 riastrad vzip.32 q4, q5
283 1.1 riastrad vzip.32 q6, q7
284 1.1 riastrad
285 1.1 riastrad vadd.u32 q8, q8, q9 /* q8 := (blkno,blkno+1,blkno+2,blkno+3) */
286 1.1 riastrad vld1.32 {q9}, [r4] /* q9 := constant */
287 1.1 riastrad vadd.u32 q12, q12, q8 /* q12 += (blkno,blkno+1,blkno+2,blkno+3) */
288 1.1 riastrad vld1.32 {q8}, [r3]! /* q8 := key[0:16) */
289 1.1 riastrad
290 1.1 riastrad vswp d1, d4
291 1.1 riastrad vswp d9, d12
292 1.1 riastrad vswp d3, d6
293 1.1 riastrad vswp d11, d14
294 1.1 riastrad
295 1.1 riastrad /*
296 1.1 riastrad * At this point, the blocks are:
297 1.1 riastrad *
298 1.1 riastrad * q0 = (x0[0], x0[1]; x0[2], x0[3])
299 1.1 riastrad * q1 = (x2[0], x2[1]; x2[2], x2[3])
300 1.1 riastrad * q2 = (x1[0], x1[1]; x1[2], x1[3])
301 1.1 riastrad * q3 = (x3[0], x3[1]; x3[2], x3[3])
302 1.1 riastrad * q4 = (x0[4], x0[5]; x0[6], x0[7])
303 1.1 riastrad * q5 = (x2[4], x2[5]; x2[6], x2[7])
304 1.1 riastrad * q6 = (x1[4], x1[5]; x1[6], x1[7])
305 1.1 riastrad * q7 = (x3[4], x3[5]; x3[6], x3[7])
306 1.1 riastrad *
307 1.1 riastrad * The first two rows to write out are q0 = x0[0:4) and q4 =
308 1.2 riastrad * x0[4:8). Swapping q1<->q4, q3<->q6, q9<->q12, and q11<->q14
309 1.2 riastrad * enables us to issue all stores in consecutive pairs:
310 1.2 riastrad * x0 in q0-q1
311 1.2 riastrad * x1 in q8-q9
312 1.2 riastrad * x2 in q2-q3
313 1.2 riastrad * x3 in q10-q11
314 1.2 riastrad * x4 in q4-q5
315 1.2 riastrad * x5 in q12-q3
316 1.2 riastrad * x6 in q6-q7
317 1.2 riastrad * x7 in q14-q15
318 1.1 riastrad */
319 1.1 riastrad
320 1.1 riastrad vswp q1, q4
321 1.2 riastrad vswp q3, q6
322 1.1 riastrad
323 1.1 riastrad vadd.u32 q0, q0, q9
324 1.1 riastrad vadd.u32 q4, q4, q9
325 1.1 riastrad vadd.u32 q2, q2, q9
326 1.2 riastrad vadd.u32 q6, q6, q9
327 1.1 riastrad
328 1.1 riastrad vadd.u32 q1, q1, q8
329 1.1 riastrad vadd.u32 q5, q5, q8
330 1.2 riastrad vadd.u32 q3, q3, q8
331 1.1 riastrad vadd.u32 q7, q7, q8
332 1.1 riastrad
333 1.1 riastrad vld1.32 {q8-q9}, [fp, :256] /* restore q8-q9 */
334 1.1 riastrad
335 1.1 riastrad LE32TOH(q0)
336 1.1 riastrad LE32TOH(q1)
337 1.1 riastrad LE32TOH(q2)
338 1.1 riastrad LE32TOH(q3)
339 1.1 riastrad LE32TOH(q4)
340 1.1 riastrad LE32TOH(q5)
341 1.1 riastrad LE32TOH(q6)
342 1.1 riastrad LE32TOH(q7)
343 1.1 riastrad
344 1.1 riastrad vst1.32 {q0-q1}, [r0]!
345 1.1 riastrad vld1.32 {q0}, [r3] /* q0 := key[16:32) */
346 1.1 riastrad mov r3, #0 /* q1 = (0, nonce[0:4), ..., nonce[8:12)) */
347 1.1 riastrad vmov d2, r3, r6
348 1.1 riastrad vmov d3, r8, r10
349 1.1 riastrad
350 1.1 riastrad vzip.32 q8, q9
351 1.1 riastrad vzip.32 q10, q11
352 1.1 riastrad vzip.32 q12, q13
353 1.1 riastrad vzip.32 q14, q15
354 1.1 riastrad
355 1.1 riastrad vswp d17, d20
356 1.1 riastrad vswp d25, d28
357 1.1 riastrad vswp d19, d22
358 1.1 riastrad vswp d27, d30
359 1.1 riastrad
360 1.2 riastrad vswp q9, q12
361 1.2 riastrad vswp q11, q14
362 1.2 riastrad
363 1.1 riastrad vadd.u32 q8, q8, q0
364 1.2 riastrad vadd.u32 q12, q12, q0
365 1.1 riastrad vadd.u32 q10, q10, q0
366 1.2 riastrad vadd.u32 q14, q14, q0
367 1.1 riastrad
368 1.2 riastrad vadd.u32 q9, q9, q1
369 1.1 riastrad vadd.u32 q13, q13, q1
370 1.2 riastrad vadd.u32 q11, q11, q1
371 1.1 riastrad vadd.u32 q15, q15, q1
372 1.1 riastrad
373 1.1 riastrad LE32TOH(q8)
374 1.1 riastrad LE32TOH(q9)
375 1.1 riastrad LE32TOH(q10)
376 1.1 riastrad LE32TOH(q11)
377 1.1 riastrad LE32TOH(q12)
378 1.1 riastrad LE32TOH(q13)
379 1.1 riastrad LE32TOH(q14)
380 1.1 riastrad LE32TOH(q15)
381 1.1 riastrad
382 1.2 riastrad /* vst1.32 {q0-q1}, [r0]! */
383 1.2 riastrad vst1.32 {q8-q9}, [r0]!
384 1.2 riastrad vst1.32 {q2-q3}, [r0]!
385 1.2 riastrad vst1.32 {q10-q11}, [r0]!
386 1.2 riastrad vst1.32 {q4-q5}, [r0]!
387 1.2 riastrad vst1.32 {q12-q13}, [r0]!
388 1.2 riastrad vst1.32 {q6-q7}, [r0]!
389 1.2 riastrad vst1.32 {q14-q15}, [r0]
390 1.2 riastrad
391 1.2 riastrad /* zero temporary space on the stack */
392 1.1 riastrad vmov.i32 q0, #0
393 1.1 riastrad vmov.i32 q1, #0
394 1.1 riastrad vst1.8 {q0-q1}, [fp, :256]
395 1.1 riastrad
396 1.1 riastrad /* restore callee-saves registers and stack */
397 1.1 riastrad vpop {d8-d15}
398 1.1 riastrad pop {r4, r5, r6, r7, r8, r10, fp, lr}
399 1.1 riastrad bx lr
400 1.1 riastrad END(chacha_stream256_neon)
401 1.1 riastrad
402 1.1 riastrad /*
403 1.1 riastrad * chacha_stream_xor256_neon(uint8_t s[256]@r0, const uint8_t p[256]@r1,
404 1.1 riastrad * uint32_t blkno@r2,
405 1.1 riastrad * const uint8_t nonce[12]@r3,
406 1.1 riastrad * const uint8_t key[32]@sp[0],
407 1.1 riastrad * const uint8_t const[16]@sp[4],
408 1.1 riastrad * unsigned nr@sp[8])
409 1.1 riastrad */
410 1.1 riastrad ENTRY(chacha_stream_xor256_neon)
411 1.1 riastrad /* save callee-saves registers */
412 1.1 riastrad push {r4, r5, r6, r7, r8, r10, fp, lr}
413 1.1 riastrad vpush {d8-d15}
414 1.1 riastrad
415 1.1 riastrad /* r7 := .Lconstants - .Lconstants_addr, r6 := .Lconstants_addr */
416 1.1 riastrad ldr r7, .Lconstants_addr
417 1.1 riastrad adr r6, .Lconstants_addr
418 1.1 riastrad
419 1.1 riastrad /* reserve space for two 128-bit/16-byte q registers */
420 1.1 riastrad sub fp, sp, #0x20
421 1.1 riastrad bic fp, fp, #0x1f /* align */
422 1.1 riastrad
423 1.1 riastrad /* get parameters */
424 1.1 riastrad add ip, sp, #96
425 1.1 riastrad add r7, r7, r6 /* r7 := .Lconstants (= v0123) */
426 1.1 riastrad ldm ip, {r4, r5, ip} /* r4 := key, r5 := const, ip := nr */
427 1.1 riastrad ldm r3, {r6, r8, r10} /* (r6, r8, r10) := nonce[0:12) */
428 1.1 riastrad
429 1.1 riastrad vld1.32 {q12}, [r5] /* q12 := constant */
430 1.1 riastrad vld1.32 {q13-q14}, [r4] /* q13-q14 := key */
431 1.1 riastrad vld1.32 {q15}, [r7, :128]! /* q15 := (0, 1, 2, 3) (128-bit aligned) */
432 1.1 riastrad
433 1.1 riastrad vdup.32 q0, d24[0] /* q0-q3 := constant */
434 1.1 riastrad vdup.32 q1, d24[1]
435 1.1 riastrad vdup.32 q2, d25[0]
436 1.1 riastrad vdup.32 q3, d25[1]
437 1.1 riastrad vdup.32 q12, r2 /* q12 := (blkno, blkno, blkno, blkno) */
438 1.1 riastrad vdup.32 q4, d26[0] /* q4-q11 := (key, key, key, key) */
439 1.1 riastrad vdup.32 q5, d26[1]
440 1.1 riastrad vdup.32 q6, d27[0]
441 1.1 riastrad vdup.32 q7, d27[1]
442 1.1 riastrad vdup.32 q8, d28[0]
443 1.1 riastrad vdup.32 q9, d28[1]
444 1.1 riastrad vdup.32 q10, d29[0]
445 1.1 riastrad vdup.32 q11, d29[1]
446 1.1 riastrad vadd.u32 q12, q12, q15 /* q12 := (blkno,blkno+1,blkno+2,blkno+3) */
447 1.1 riastrad vdup.32 q13, r6 /* q13-q15 := nonce */
448 1.1 riastrad vdup.32 q14, r8
449 1.1 riastrad vdup.32 q15, r10
450 1.1 riastrad
451 1.1 riastrad HTOLE32(q0)
452 1.1 riastrad HTOLE32(q1)
453 1.1 riastrad HTOLE32(q2)
454 1.1 riastrad HTOLE32(q3)
455 1.1 riastrad HTOLE32(q4)
456 1.1 riastrad HTOLE32(q5)
457 1.1 riastrad HTOLE32(q6)
458 1.1 riastrad HTOLE32(q7)
459 1.1 riastrad HTOLE32(q8)
460 1.1 riastrad HTOLE32(q9)
461 1.1 riastrad HTOLE32(q10)
462 1.1 riastrad HTOLE32(q11)
463 1.1 riastrad HTOLE32(q12)
464 1.1 riastrad HTOLE32(q13)
465 1.1 riastrad HTOLE32(q14)
466 1.1 riastrad HTOLE32(q15)
467 1.1 riastrad
468 1.1 riastrad b 2f
469 1.1 riastrad
470 1.1 riastrad _ALIGN_TEXT
471 1.1 riastrad 1: ROUNDLD q0,q1,q2,q3, q5,q6,q7,q4, q10,q11,q8,q9, q15,q12,q13,q14
472 1.1 riastrad 2: subs ip, ip, #2
473 1.1 riastrad ROUND q0,q1,q2,q3, q4,q5,q6,q7, q8,q9,q10,q11, q12,q13,q14,q15, \
474 1.1 riastrad d16, d24,d25, d26,d27, d28,d29, d30,d31
475 1.1 riastrad ROUNDLD q0,q1,q2,q3, q4,q5,q6,q7, q8,q9,q10,q11, q12,q13,q14,q15
476 1.1 riastrad ROUND q0,q1,q2,q3, q5,q6,q7,q4, q10,q11,q8,q9, q15,q12,q13,q14, \
477 1.1 riastrad d20, d30,d31, d24,d25, d26,d27, d28,d29
478 1.1 riastrad bne 1b
479 1.1 riastrad
480 1.1 riastrad /*
481 1.1 riastrad * q8-q9 are free / saved on the stack. Now for the real fun:
482 1.1 riastrad * in only 16 registers, compute p[i] ^ (y[i] + x[i]) for i in
483 1.1 riastrad * {0,1,2,...,15}. The twist is that the p[i] and the y[i] are
484 1.1 riastrad * transposed from one another, and the x[i] are in general
485 1.2 riastrad * registers and memory. See comments in chacha_stream256_neon
486 1.2 riastrad * for the layout with swaps.
487 1.1 riastrad */
488 1.1 riastrad
489 1.1 riastrad sub r7, r7, #0x10
490 1.1 riastrad vdup.32 q8, r2 /* q8 := (blkno, blkno, blkno, blkno) */
491 1.1 riastrad vld1.32 {q9}, [r7, :128] /* q9 := (0, 1, 2, 3) */
492 1.1 riastrad
493 1.1 riastrad vzip.32 q0, q1
494 1.1 riastrad vzip.32 q2, q3
495 1.1 riastrad vzip.32 q4, q5
496 1.1 riastrad vzip.32 q6, q7
497 1.1 riastrad
498 1.1 riastrad vadd.u32 q8, q8, q9 /* q8 := (blkno,blkno+1,blkno+2,blkno+3) */
499 1.1 riastrad vld1.32 {q9}, [r5] /* q9 := constant */
500 1.1 riastrad vadd.u32 q12, q12, q8 /* q12 += (blkno,blkno+1,blkno+2,blkno+3) */
501 1.1 riastrad vld1.32 {q8}, [r4]! /* q8 := key[0:16) */
502 1.1 riastrad
503 1.2 riastrad vswp d3, d6
504 1.2 riastrad vswp d9, d12
505 1.1 riastrad vswp d1, d4
506 1.1 riastrad vswp d11, d14
507 1.1 riastrad
508 1.1 riastrad vswp q1, q4
509 1.2 riastrad vswp q3, q6
510 1.1 riastrad
511 1.1 riastrad vadd.u32 q0, q0, q9
512 1.1 riastrad vadd.u32 q4, q4, q9
513 1.1 riastrad vadd.u32 q2, q2, q9
514 1.2 riastrad vadd.u32 q6, q6, q9
515 1.1 riastrad
516 1.1 riastrad vadd.u32 q1, q1, q8
517 1.1 riastrad vadd.u32 q5, q5, q8
518 1.2 riastrad vadd.u32 q3, q3, q8
519 1.1 riastrad vadd.u32 q7, q7, q8
520 1.1 riastrad
521 1.1 riastrad vld1.32 {q8-q9}, [r1]! /* load plaintext bytes [0:32) */
522 1.1 riastrad
523 1.1 riastrad LE32TOH(q0)
524 1.1 riastrad LE32TOH(q1)
525 1.1 riastrad LE32TOH(q2)
526 1.1 riastrad LE32TOH(q6)
527 1.1 riastrad LE32TOH(q4)
528 1.1 riastrad LE32TOH(q5)
529 1.1 riastrad LE32TOH(q3)
530 1.1 riastrad LE32TOH(q7)
531 1.1 riastrad
532 1.1 riastrad veor q0, q0, q8 /* compute ciphertext bytes [0:32) */
533 1.1 riastrad veor q1, q1, q9
534 1.1 riastrad
535 1.1 riastrad vld1.32 {q8-q9}, [fp, :256] /* restore q8-q9 */
536 1.1 riastrad
537 1.1 riastrad vst1.32 {q0-q1}, [r0]! /* store ciphertext bytes [0:32) */
538 1.1 riastrad vld1.32 {q0}, [r4] /* q0 := key[16:32) */
539 1.1 riastrad mov r3, #0 /* q1 = (0, nonce[0:4), ..., nonce[8:12)) */
540 1.1 riastrad vmov d2, r3, r6
541 1.1 riastrad vmov d3, r8, r10
542 1.1 riastrad
543 1.1 riastrad vzip.32 q8, q9
544 1.1 riastrad vzip.32 q10, q11
545 1.1 riastrad vzip.32 q12, q13
546 1.1 riastrad vzip.32 q14, q15
547 1.1 riastrad
548 1.2 riastrad vswp d19, d22
549 1.2 riastrad vswp d25, d28
550 1.1 riastrad vswp d17, d20
551 1.1 riastrad vswp d27, d30
552 1.1 riastrad
553 1.1 riastrad vswp q9, q12 /* free up q9 earlier for consecutive q8-q9 */
554 1.2 riastrad vswp q11, q14
555 1.1 riastrad
556 1.1 riastrad vadd.u32 q8, q8, q0
557 1.1 riastrad vadd.u32 q12, q12, q0
558 1.1 riastrad vadd.u32 q10, q10, q0
559 1.2 riastrad vadd.u32 q14, q14, q0
560 1.1 riastrad
561 1.1 riastrad vadd.u32 q9, q9, q1
562 1.1 riastrad vadd.u32 q13, q13, q1
563 1.2 riastrad vadd.u32 q11, q11, q1
564 1.1 riastrad vadd.u32 q15, q15, q1
565 1.1 riastrad
566 1.1 riastrad vld1.32 {q0-q1}, [r1]! /* load plaintext bytes [32:64) */
567 1.1 riastrad
568 1.1 riastrad LE32TOH(q8)
569 1.1 riastrad LE32TOH(q9)
570 1.1 riastrad LE32TOH(q10)
571 1.2 riastrad LE32TOH(q11)
572 1.1 riastrad LE32TOH(q12)
573 1.1 riastrad LE32TOH(q13)
574 1.2 riastrad LE32TOH(q14)
575 1.1 riastrad LE32TOH(q15)
576 1.1 riastrad
577 1.1 riastrad veor q0, q0, q8 /* compute ciphertext bytes [32:64) */
578 1.1 riastrad veor q1, q1, q9
579 1.1 riastrad
580 1.1 riastrad vld1.32 {q8-q9}, [r1]! /* load plaintext bytes [64:96) */
581 1.1 riastrad vst1.32 {q0-q1}, [r0]! /* store ciphertext bytes [32:64) */
582 1.1 riastrad vld1.32 {q0-q1}, [r1]! /* load plaintext bytes [96:128) */
583 1.1 riastrad
584 1.1 riastrad veor q2, q2, q8 /* compute ciphertext bytes [64:96) */
585 1.2 riastrad veor q3, q3, q9
586 1.1 riastrad
587 1.1 riastrad vld1.32 {q8-q9}, [r1]! /* load plaintext bytes [128:160) */
588 1.2 riastrad vst1.32 {q2-q3}, [r0]! /* store ciphertext bytes [64:80) */
589 1.1 riastrad
590 1.1 riastrad veor q10, q10, q0 /* compute ciphertext bytes [96:128) */
591 1.2 riastrad veor q11, q11, q1
592 1.1 riastrad
593 1.1 riastrad vld1.32 {q0-q1}, [r1]! /* load plaintext bytes [160:192) */
594 1.2 riastrad vst1.32 {q10-q11}, [r0]! /* store ciphertext bytes [80:96) */
595 1.1 riastrad
596 1.1 riastrad veor q4, q4, q8 /* compute ciphertext bytes [128:160) */
597 1.1 riastrad veor q5, q5, q9
598 1.1 riastrad
599 1.1 riastrad vld1.32 {q8-q9}, [r1]! /* load plaintext bytes [192:224) */
600 1.2 riastrad vst1.32 {q4-q5}, [r0]! /* store ciphertext bytes [96:112) */
601 1.1 riastrad
602 1.1 riastrad veor q12, q12, q0 /* compute ciphertext bytes [160:192) */
603 1.1 riastrad veor q13, q13, q1
604 1.1 riastrad
605 1.1 riastrad vld1.32 {q0-q1}, [r1] /* load plaintext bytes [224:256) */
606 1.2 riastrad vst1.32 {q12-q13}, [r0]! /* store ciphertext bytes [112:128) */
607 1.1 riastrad
608 1.2 riastrad veor q6, q6, q8 /* compute ciphertext bytes [192:224) */
609 1.2 riastrad veor q7, q7, q9
610 1.1 riastrad
611 1.2 riastrad vst1.32 {q6-q7}, [r0]! /* store ciphertext bytes [192:224) */
612 1.1 riastrad
613 1.2 riastrad veor q14, q14, q0 /* compute ciphertext bytes [224:256) */
614 1.2 riastrad veor q15, q15, q1
615 1.1 riastrad
616 1.2 riastrad vst1.32 {q14-q15}, [r0] /* store ciphertext bytes [224:256) */
617 1.1 riastrad
618 1.1 riastrad /* zero temporary space on the stack */
619 1.1 riastrad vmov.i32 q0, #0
620 1.1 riastrad vmov.i32 q1, #0
621 1.1 riastrad vst1.8 {q0-q1}, [fp, :256]
622 1.1 riastrad
623 1.1 riastrad /* restore callee-saves registers and stack */
624 1.1 riastrad vpop {d8-d15}
625 1.1 riastrad pop {r4, r5, r6, r7, r8, r10, fp, lr}
626 1.1 riastrad bx lr
627 1.1 riastrad END(chacha_stream_xor256_neon)
628 1.1 riastrad
629 1.1 riastrad .section .rodata
630 1.1 riastrad .p2align 4
631 1.1 riastrad .Lconstants:
632 1.1 riastrad
633 1.1 riastrad .type v0123,%object
634 1.1 riastrad v0123:
635 1.1 riastrad .long 0, 1, 2, 3
636 1.1 riastrad END(v0123)
637 1.1 riastrad
638 1.1 riastrad .type rot8,%object
639 1.1 riastrad rot8:
640 1.1 riastrad .long 0x02010003, 0x06050407
641 1.1 riastrad END(rot8)
642