~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/arm/crypto/chacha-neon-core.S

Version: ~ [ linux-6.11-rc3 ] ~ [ linux-6.10.4 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.45 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.104 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.164 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.223 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.281 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.319 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  * ChaCha/XChaCha NEON helper functions
  3  *
  4  * Copyright (C) 2016 Linaro, Ltd. <ard.biesheuvel@linaro.org>
  5  *
  6  * This program is free software; you can redistribute it and/or modify
  7  * it under the terms of the GNU General Public License version 2 as
  8  * published by the Free Software Foundation.
  9  *
 10  * Based on:
 11  * ChaCha20 256-bit cipher algorithm, RFC7539, x64 SSE3 functions
 12  *
 13  * Copyright (C) 2015 Martin Willi
 14  *
 15  * This program is free software; you can redistribute it and/or modify
 16  * it under the terms of the GNU General Public License as published by
 17  * the Free Software Foundation; either version 2 of the License, or
 18  * (at your option) any later version.
 19  */
 20 
 21  /*
 22   * NEON doesn't have a rotate instruction.  The alternatives are, more or less:
 23   *
 24   * (a)  vshl.u32 + vsri.u32            (needs temporary register)
 25   * (b)  vshl.u32 + vshr.u32 + vorr     (needs temporary register)
 26   * (c)  vrev32.16                      (16-bit rotations only)
 27   * (d)  vtbl.8 + vtbl.8                (multiple of 8 bits rotations only,
 28   *                                      needs index vector)
 29   *
 30   * ChaCha has 16, 12, 8, and 7-bit rotations.  For the 12 and 7-bit rotations,
 31   * the only choices are (a) and (b).  We use (a) since it takes two-thirds the
 32   * cycles of (b) on both Cortex-A7 and Cortex-A53.
 33   *
 34   * For the 16-bit rotation, we use vrev32.16 since it's consistently fastest
 35   * and doesn't need a temporary register.
 36   *
 37   * For the 8-bit rotation, we use vtbl.8 + vtbl.8.  On Cortex-A7, this sequence
 38   * is twice as fast as (a), even when doing (a) on multiple registers
 39   * simultaneously to eliminate the stall between vshl and vsri.  Also, it
 40   * parallelizes better when temporary registers are scarce.
 41   *
 42   * A disadvantage is that on Cortex-A53, the vtbl sequence is the same speed as
 43   * (a), so the need to load the rotation table actually makes the vtbl method
 44   * slightly slower overall on that CPU (~1.3% slower ChaCha20).  Still, it
 45   * seems to be a good compromise to get a more significant speed boost on some
 46   * CPUs, e.g. ~4.8% faster ChaCha20 on Cortex-A7.
 47   */
 48 
 49 #include <linux/linkage.h>
 50 #include <asm/cache.h>
 51 
 52         .text
 53         .fpu            neon
 54         .align          5
 55 
 56 /*
 57  * chacha_permute - permute one block
 58  *
 59  * Permute one 64-byte block where the state matrix is stored in the four NEON
 60  * registers q0-q3.  It performs matrix operations on four words in parallel,
 61  * but requires shuffling to rearrange the words after each round.
 62  *
 63  * The round count is given in r3.
 64  *
 65  * Clobbers: r3, ip, q4-q5
 66  */
 67 chacha_permute:
 68 
 69         adr             ip, .Lrol8_table
 70         vld1.8          {d10}, [ip, :64]
 71 
 72 .Ldoubleround:
 73         // x0 += x1, x3 = rotl32(x3 ^ x0, 16)
 74         vadd.i32        q0, q0, q1
 75         veor            q3, q3, q0
 76         vrev32.16       q3, q3
 77 
 78         // x2 += x3, x1 = rotl32(x1 ^ x2, 12)
 79         vadd.i32        q2, q2, q3
 80         veor            q4, q1, q2
 81         vshl.u32        q1, q4, #12
 82         vsri.u32        q1, q4, #20
 83 
 84         // x0 += x1, x3 = rotl32(x3 ^ x0, 8)
 85         vadd.i32        q0, q0, q1
 86         veor            q3, q3, q0
 87         vtbl.8          d6, {d6}, d10
 88         vtbl.8          d7, {d7}, d10
 89 
 90         // x2 += x3, x1 = rotl32(x1 ^ x2, 7)
 91         vadd.i32        q2, q2, q3
 92         veor            q4, q1, q2
 93         vshl.u32        q1, q4, #7
 94         vsri.u32        q1, q4, #25
 95 
 96         // x1 = shuffle32(x1, MASK(0, 3, 2, 1))
 97         vext.8          q1, q1, q1, #4
 98         // x2 = shuffle32(x2, MASK(1, 0, 3, 2))
 99         vext.8          q2, q2, q2, #8
100         // x3 = shuffle32(x3, MASK(2, 1, 0, 3))
101         vext.8          q3, q3, q3, #12
102 
103         // x0 += x1, x3 = rotl32(x3 ^ x0, 16)
104         vadd.i32        q0, q0, q1
105         veor            q3, q3, q0
106         vrev32.16       q3, q3
107 
108         // x2 += x3, x1 = rotl32(x1 ^ x2, 12)
109         vadd.i32        q2, q2, q3
110         veor            q4, q1, q2
111         vshl.u32        q1, q4, #12
112         vsri.u32        q1, q4, #20
113 
114         // x0 += x1, x3 = rotl32(x3 ^ x0, 8)
115         vadd.i32        q0, q0, q1
116         veor            q3, q3, q0
117         vtbl.8          d6, {d6}, d10
118         vtbl.8          d7, {d7}, d10
119 
120         // x2 += x3, x1 = rotl32(x1 ^ x2, 7)
121         vadd.i32        q2, q2, q3
122         veor            q4, q1, q2
123         vshl.u32        q1, q4, #7
124         vsri.u32        q1, q4, #25
125 
126         // x1 = shuffle32(x1, MASK(2, 1, 0, 3))
127         vext.8          q1, q1, q1, #12
128         // x2 = shuffle32(x2, MASK(1, 0, 3, 2))
129         vext.8          q2, q2, q2, #8
130         // x3 = shuffle32(x3, MASK(0, 3, 2, 1))
131         vext.8          q3, q3, q3, #4
132 
133         subs            r3, r3, #2
134         bne             .Ldoubleround
135 
136         bx              lr
137 ENDPROC(chacha_permute)
138 
139 ENTRY(chacha_block_xor_neon)
140         // r0: Input state matrix, s
141         // r1: 1 data block output, o
142         // r2: 1 data block input, i
143         // r3: nrounds
144         push            {lr}
145 
146         // x0..3 = s0..3
147         add             ip, r0, #0x20
148         vld1.32         {q0-q1}, [r0]
149         vld1.32         {q2-q3}, [ip]
150 
151         vmov            q8, q0
152         vmov            q9, q1
153         vmov            q10, q2
154         vmov            q11, q3
155 
156         bl              chacha_permute
157 
158         add             ip, r2, #0x20
159         vld1.8          {q4-q5}, [r2]
160         vld1.8          {q6-q7}, [ip]
161 
162         // o0 = i0 ^ (x0 + s0)
163         vadd.i32        q0, q0, q8
164         veor            q0, q0, q4
165 
166         // o1 = i1 ^ (x1 + s1)
167         vadd.i32        q1, q1, q9
168         veor            q1, q1, q5
169 
170         // o2 = i2 ^ (x2 + s2)
171         vadd.i32        q2, q2, q10
172         veor            q2, q2, q6
173 
174         // o3 = i3 ^ (x3 + s3)
175         vadd.i32        q3, q3, q11
176         veor            q3, q3, q7
177 
178         add             ip, r1, #0x20
179         vst1.8          {q0-q1}, [r1]
180         vst1.8          {q2-q3}, [ip]
181 
182         pop             {pc}
183 ENDPROC(chacha_block_xor_neon)
184 
185 ENTRY(hchacha_block_neon)
186         // r0: Input state matrix, s
187         // r1: output (8 32-bit words)
188         // r2: nrounds
189         push            {lr}
190 
191         vld1.32         {q0-q1}, [r0]!
192         vld1.32         {q2-q3}, [r0]
193 
194         mov             r3, r2
195         bl              chacha_permute
196 
197         vst1.32         {q0}, [r1]!
198         vst1.32         {q3}, [r1]
199 
200         pop             {pc}
201 ENDPROC(hchacha_block_neon)
202 
203         .align          4
204 .Lctrinc:       .word   0, 1, 2, 3
205 .Lrol8_table:   .byte   3, 0, 1, 2, 7, 4, 5, 6
206 
207         .align          5
208 ENTRY(chacha_4block_xor_neon)
209         push            {r4, lr}
210         mov             r4, sp                  // preserve the stack pointer
211         sub             ip, sp, #0x20           // allocate a 32 byte buffer
212         bic             ip, ip, #0x1f           // aligned to 32 bytes
213         mov             sp, ip
214 
215         // r0: Input state matrix, s
216         // r1: 4 data blocks output, o
217         // r2: 4 data blocks input, i
218         // r3: nrounds
219 
220         //
221         // This function encrypts four consecutive ChaCha blocks by loading
222         // the state matrix in NEON registers four times. The algorithm performs
223         // each operation on the corresponding word of each state matrix, hence
224         // requires no word shuffling. The words are re-interleaved before the
225         // final addition of the original state and the XORing step.
226         //
227 
228         // x0..15[0-3] = s0..15[0-3]
229         add             ip, r0, #0x20
230         vld1.32         {q0-q1}, [r0]
231         vld1.32         {q2-q3}, [ip]
232 
233         adr             lr, .Lctrinc
234         vdup.32         q15, d7[1]
235         vdup.32         q14, d7[0]
236         vld1.32         {q4}, [lr, :128]
237         vdup.32         q13, d6[1]
238         vdup.32         q12, d6[0]
239         vdup.32         q11, d5[1]
240         vdup.32         q10, d5[0]
241         vadd.u32        q12, q12, q4            // x12 += counter values 0-3
242         vdup.32         q9, d4[1]
243         vdup.32         q8, d4[0]
244         vdup.32         q7, d3[1]
245         vdup.32         q6, d3[0]
246         vdup.32         q5, d2[1]
247         vdup.32         q4, d2[0]
248         vdup.32         q3, d1[1]
249         vdup.32         q2, d1[0]
250         vdup.32         q1, d0[1]
251         vdup.32         q0, d0[0]
252 
253         adr             ip, .Lrol8_table
254         b               1f
255 
256 .Ldoubleround4:
257         vld1.32         {q8-q9}, [sp, :256]
258 1:
259         // x0 += x4, x12 = rotl32(x12 ^ x0, 16)
260         // x1 += x5, x13 = rotl32(x13 ^ x1, 16)
261         // x2 += x6, x14 = rotl32(x14 ^ x2, 16)
262         // x3 += x7, x15 = rotl32(x15 ^ x3, 16)
263         vadd.i32        q0, q0, q4
264         vadd.i32        q1, q1, q5
265         vadd.i32        q2, q2, q6
266         vadd.i32        q3, q3, q7
267 
268         veor            q12, q12, q0
269         veor            q13, q13, q1
270         veor            q14, q14, q2
271         veor            q15, q15, q3
272 
273         vrev32.16       q12, q12
274         vrev32.16       q13, q13
275         vrev32.16       q14, q14
276         vrev32.16       q15, q15
277 
278         // x8 += x12, x4 = rotl32(x4 ^ x8, 12)
279         // x9 += x13, x5 = rotl32(x5 ^ x9, 12)
280         // x10 += x14, x6 = rotl32(x6 ^ x10, 12)
281         // x11 += x15, x7 = rotl32(x7 ^ x11, 12)
282         vadd.i32        q8, q8, q12
283         vadd.i32        q9, q9, q13
284         vadd.i32        q10, q10, q14
285         vadd.i32        q11, q11, q15
286 
287         vst1.32         {q8-q9}, [sp, :256]
288 
289         veor            q8, q4, q8
290         veor            q9, q5, q9
291         vshl.u32        q4, q8, #12
292         vshl.u32        q5, q9, #12
293         vsri.u32        q4, q8, #20
294         vsri.u32        q5, q9, #20
295 
296         veor            q8, q6, q10
297         veor            q9, q7, q11
298         vshl.u32        q6, q8, #12
299         vshl.u32        q7, q9, #12
300         vsri.u32        q6, q8, #20
301         vsri.u32        q7, q9, #20
302 
303         // x0 += x4, x12 = rotl32(x12 ^ x0, 8)
304         // x1 += x5, x13 = rotl32(x13 ^ x1, 8)
305         // x2 += x6, x14 = rotl32(x14 ^ x2, 8)
306         // x3 += x7, x15 = rotl32(x15 ^ x3, 8)
307         vld1.8          {d16}, [ip, :64]
308         vadd.i32        q0, q0, q4
309         vadd.i32        q1, q1, q5
310         vadd.i32        q2, q2, q6
311         vadd.i32        q3, q3, q7
312 
313         veor            q12, q12, q0
314         veor            q13, q13, q1
315         veor            q14, q14, q2
316         veor            q15, q15, q3
317 
318         vtbl.8          d24, {d24}, d16
319         vtbl.8          d25, {d25}, d16
320         vtbl.8          d26, {d26}, d16
321         vtbl.8          d27, {d27}, d16
322         vtbl.8          d28, {d28}, d16
323         vtbl.8          d29, {d29}, d16
324         vtbl.8          d30, {d30}, d16
325         vtbl.8          d31, {d31}, d16
326 
327         vld1.32         {q8-q9}, [sp, :256]
328 
329         // x8 += x12, x4 = rotl32(x4 ^ x8, 7)
330         // x9 += x13, x5 = rotl32(x5 ^ x9, 7)
331         // x10 += x14, x6 = rotl32(x6 ^ x10, 7)
332         // x11 += x15, x7 = rotl32(x7 ^ x11, 7)
333         vadd.i32        q8, q8, q12
334         vadd.i32        q9, q9, q13
335         vadd.i32        q10, q10, q14
336         vadd.i32        q11, q11, q15
337 
338         vst1.32         {q8-q9}, [sp, :256]
339 
340         veor            q8, q4, q8
341         veor            q9, q5, q9
342         vshl.u32        q4, q8, #7
343         vshl.u32        q5, q9, #7
344         vsri.u32        q4, q8, #25
345         vsri.u32        q5, q9, #25
346 
347         veor            q8, q6, q10
348         veor            q9, q7, q11
349         vshl.u32        q6, q8, #7
350         vshl.u32        q7, q9, #7
351         vsri.u32        q6, q8, #25
352         vsri.u32        q7, q9, #25
353 
354         vld1.32         {q8-q9}, [sp, :256]
355 
356         // x0 += x5, x15 = rotl32(x15 ^ x0, 16)
357         // x1 += x6, x12 = rotl32(x12 ^ x1, 16)
358         // x2 += x7, x13 = rotl32(x13 ^ x2, 16)
359         // x3 += x4, x14 = rotl32(x14 ^ x3, 16)
360         vadd.i32        q0, q0, q5
361         vadd.i32        q1, q1, q6
362         vadd.i32        q2, q2, q7
363         vadd.i32        q3, q3, q4
364 
365         veor            q15, q15, q0
366         veor            q12, q12, q1
367         veor            q13, q13, q2
368         veor            q14, q14, q3
369 
370         vrev32.16       q15, q15
371         vrev32.16       q12, q12
372         vrev32.16       q13, q13
373         vrev32.16       q14, q14
374 
375         // x10 += x15, x5 = rotl32(x5 ^ x10, 12)
376         // x11 += x12, x6 = rotl32(x6 ^ x11, 12)
377         // x8 += x13, x7 = rotl32(x7 ^ x8, 12)
378         // x9 += x14, x4 = rotl32(x4 ^ x9, 12)
379         vadd.i32        q10, q10, q15
380         vadd.i32        q11, q11, q12
381         vadd.i32        q8, q8, q13
382         vadd.i32        q9, q9, q14
383 
384         vst1.32         {q8-q9}, [sp, :256]
385 
386         veor            q8, q7, q8
387         veor            q9, q4, q9
388         vshl.u32        q7, q8, #12
389         vshl.u32        q4, q9, #12
390         vsri.u32        q7, q8, #20
391         vsri.u32        q4, q9, #20
392 
393         veor            q8, q5, q10
394         veor            q9, q6, q11
395         vshl.u32        q5, q8, #12
396         vshl.u32        q6, q9, #12
397         vsri.u32        q5, q8, #20
398         vsri.u32        q6, q9, #20
399 
400         // x0 += x5, x15 = rotl32(x15 ^ x0, 8)
401         // x1 += x6, x12 = rotl32(x12 ^ x1, 8)
402         // x2 += x7, x13 = rotl32(x13 ^ x2, 8)
403         // x3 += x4, x14 = rotl32(x14 ^ x3, 8)
404         vld1.8          {d16}, [ip, :64]
405         vadd.i32        q0, q0, q5
406         vadd.i32        q1, q1, q6
407         vadd.i32        q2, q2, q7
408         vadd.i32        q3, q3, q4
409 
410         veor            q15, q15, q0
411         veor            q12, q12, q1
412         veor            q13, q13, q2
413         veor            q14, q14, q3
414 
415         vtbl.8          d30, {d30}, d16
416         vtbl.8          d31, {d31}, d16
417         vtbl.8          d24, {d24}, d16
418         vtbl.8          d25, {d25}, d16
419         vtbl.8          d26, {d26}, d16
420         vtbl.8          d27, {d27}, d16
421         vtbl.8          d28, {d28}, d16
422         vtbl.8          d29, {d29}, d16
423 
424         vld1.32         {q8-q9}, [sp, :256]
425 
426         // x10 += x15, x5 = rotl32(x5 ^ x10, 7)
427         // x11 += x12, x6 = rotl32(x6 ^ x11, 7)
428         // x8 += x13, x7 = rotl32(x7 ^ x8, 7)
429         // x9 += x14, x4 = rotl32(x4 ^ x9, 7)
430         vadd.i32        q10, q10, q15
431         vadd.i32        q11, q11, q12
432         vadd.i32        q8, q8, q13
433         vadd.i32        q9, q9, q14
434 
435         vst1.32         {q8-q9}, [sp, :256]
436 
437         veor            q8, q7, q8
438         veor            q9, q4, q9
439         vshl.u32        q7, q8, #7
440         vshl.u32        q4, q9, #7
441         vsri.u32        q7, q8, #25
442         vsri.u32        q4, q9, #25
443 
444         veor            q8, q5, q10
445         veor            q9, q6, q11
446         vshl.u32        q5, q8, #7
447         vshl.u32        q6, q9, #7
448         vsri.u32        q5, q8, #25
449         vsri.u32        q6, q9, #25
450 
451         subs            r3, r3, #2
452         bne             .Ldoubleround4
453 
454         // x0..7[0-3] are in q0-q7, x10..15[0-3] are in q10-q15.
455         // x8..9[0-3] are on the stack.
456 
457         // Re-interleave the words in the first two rows of each block (x0..7).
458         // Also add the counter values 0-3 to x12[0-3].
459           vld1.32       {q8}, [lr, :128]        // load counter values 0-3
460         vzip.32         q0, q1                  // => (0 1 0 1) (0 1 0 1)
461         vzip.32         q2, q3                  // => (2 3 2 3) (2 3 2 3)
462         vzip.32         q4, q5                  // => (4 5 4 5) (4 5 4 5)
463         vzip.32         q6, q7                  // => (6 7 6 7) (6 7 6 7)
464           vadd.u32      q12, q8                 // x12 += counter values 0-3
465         vswp            d1, d4
466         vswp            d3, d6
467           vld1.32       {q8-q9}, [r0]!          // load s0..7
468         vswp            d9, d12
469         vswp            d11, d14
470 
471         // Swap q1 and q4 so that we'll free up consecutive registers (q0-q1)
472         // after XORing the first 32 bytes.
473         vswp            q1, q4
474 
475         // First two rows of each block are (q0 q1) (q2 q6) (q4 q5) (q3 q7)
476 
477         // x0..3[0-3] += s0..3[0-3]     (add orig state to 1st row of each block)
478         vadd.u32        q0, q0, q8
479         vadd.u32        q2, q2, q8
480         vadd.u32        q4, q4, q8
481         vadd.u32        q3, q3, q8
482 
483         // x4..7[0-3] += s4..7[0-3]     (add orig state to 2nd row of each block)
484         vadd.u32        q1, q1, q9
485         vadd.u32        q6, q6, q9
486         vadd.u32        q5, q5, q9
487         vadd.u32        q7, q7, q9
488 
489         // XOR first 32 bytes using keystream from first two rows of first block
490         vld1.8          {q8-q9}, [r2]!
491         veor            q8, q8, q0
492         veor            q9, q9, q1
493         vst1.8          {q8-q9}, [r1]!
494 
495         // Re-interleave the words in the last two rows of each block (x8..15).
496         vld1.32         {q8-q9}, [sp, :256]
497           mov           sp, r4          // restore original stack pointer
498           ldr           r4, [r4, #8]    // load number of bytes
499         vzip.32         q12, q13        // => (12 13 12 13) (12 13 12 13)
500         vzip.32         q14, q15        // => (14 15 14 15) (14 15 14 15)
501         vzip.32         q8, q9          // => (8 9 8 9) (8 9 8 9)
502         vzip.32         q10, q11        // => (10 11 10 11) (10 11 10 11)
503           vld1.32       {q0-q1}, [r0]   // load s8..15
504         vswp            d25, d28
505         vswp            d27, d30
506         vswp            d17, d20
507         vswp            d19, d22
508 
509         // Last two rows of each block are (q8 q12) (q10 q14) (q9 q13) (q11 q15)
510 
511         // x8..11[0-3] += s8..11[0-3]   (add orig state to 3rd row of each block)
512         vadd.u32        q8,  q8,  q0
513         vadd.u32        q10, q10, q0
514         vadd.u32        q9,  q9,  q0
515         vadd.u32        q11, q11, q0
516 
517         // x12..15[0-3] += s12..15[0-3] (add orig state to 4th row of each block)
518         vadd.u32        q12, q12, q1
519         vadd.u32        q14, q14, q1
520         vadd.u32        q13, q13, q1
521         vadd.u32        q15, q15, q1
522 
523         // XOR the rest of the data with the keystream
524 
525         vld1.8          {q0-q1}, [r2]!
526         subs            r4, r4, #96
527         veor            q0, q0, q8
528         veor            q1, q1, q12
529         ble             .Lle96
530         vst1.8          {q0-q1}, [r1]!
531 
532         vld1.8          {q0-q1}, [r2]!
533         subs            r4, r4, #32
534         veor            q0, q0, q2
535         veor            q1, q1, q6
536         ble             .Lle128
537         vst1.8          {q0-q1}, [r1]!
538 
539         vld1.8          {q0-q1}, [r2]!
540         subs            r4, r4, #32
541         veor            q0, q0, q10
542         veor            q1, q1, q14
543         ble             .Lle160
544         vst1.8          {q0-q1}, [r1]!
545 
546         vld1.8          {q0-q1}, [r2]!
547         subs            r4, r4, #32
548         veor            q0, q0, q4
549         veor            q1, q1, q5
550         ble             .Lle192
551         vst1.8          {q0-q1}, [r1]!
552 
553         vld1.8          {q0-q1}, [r2]!
554         subs            r4, r4, #32
555         veor            q0, q0, q9
556         veor            q1, q1, q13
557         ble             .Lle224
558         vst1.8          {q0-q1}, [r1]!
559 
560         vld1.8          {q0-q1}, [r2]!
561         subs            r4, r4, #32
562         veor            q0, q0, q3
563         veor            q1, q1, q7
564         blt             .Llt256
565 .Lout:
566         vst1.8          {q0-q1}, [r1]!
567 
568         vld1.8          {q0-q1}, [r2]
569         veor            q0, q0, q11
570         veor            q1, q1, q15
571         vst1.8          {q0-q1}, [r1]
572 
573         pop             {r4, pc}
574 
575 .Lle192:
576         vmov            q4, q9
577         vmov            q5, q13
578 
579 .Lle160:
580         // nothing to do
581 
582 .Lfinalblock:
583         // Process the final block if processing less than 4 full blocks.
584         // Entered with 32 bytes of ChaCha cipher stream in q4-q5, and the
585         // previous 32 byte output block that still needs to be written at
586         // [r1] in q0-q1.
587         beq             .Lfullblock
588 
589 .Lpartialblock:
590         adr             lr, .Lpermute + 32
591         add             r2, r2, r4
592         add             lr, lr, r4
593         add             r4, r4, r1
594 
595         vld1.8          {q2-q3}, [lr]
596         vld1.8          {q6-q7}, [r2]
597 
598         add             r4, r4, #32
599 
600         vtbl.8          d4, {q4-q5}, d4
601         vtbl.8          d5, {q4-q5}, d5
602         vtbl.8          d6, {q4-q5}, d6
603         vtbl.8          d7, {q4-q5}, d7
604 
605         veor            q6, q6, q2
606         veor            q7, q7, q3
607 
608         vst1.8          {q6-q7}, [r4]   // overlapping stores
609         vst1.8          {q0-q1}, [r1]
610         pop             {r4, pc}
611 
612 .Lfullblock:
613         vmov            q11, q4
614         vmov            q15, q5
615         b               .Lout
616 .Lle96:
617         vmov            q4, q2
618         vmov            q5, q6
619         b               .Lfinalblock
620 .Lle128:
621         vmov            q4, q10
622         vmov            q5, q14
623         b               .Lfinalblock
624 .Lle224:
625         vmov            q4, q3
626         vmov            q5, q7
627         b               .Lfinalblock
628 .Llt256:
629         vmov            q4, q11
630         vmov            q5, q15
631         b               .Lpartialblock
632 ENDPROC(chacha_4block_xor_neon)
633 
634         .align          L1_CACHE_SHIFT
635 .Lpermute:
636         .byte           0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07
637         .byte           0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
638         .byte           0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17
639         .byte           0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f
640         .byte           0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07
641         .byte           0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
642         .byte           0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17
643         .byte           0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php