Add ARMv7/NEON implementation of Keccak
[libgcrypt.git] / cipher / keccak-armv7-neon.S
1 /* keccak-armv7-neon.S  -  ARMv7/NEON implementation of Keccak
2  *
3  * Copyright (C) 2015 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 #include <config.h>
22
23 #if defined(HAVE_ARM_ARCH_V6) && defined(__ARMEL__) && \
24     defined(HAVE_COMPATIBLE_GCC_ARM_PLATFORM_AS) && \
25     defined(HAVE_GCC_INLINE_ASM_NEON)
26
27 /* Based on public-domain/CC0 implementation from SUPERCOP package
28  * (keccakc1024/inplace-armv7a-neon/keccak2.s)
29  *
30  * Original copyright header follows:
31  */
32
33 @ The Keccak sponge function, designed by Guido Bertoni, Joan Daemen,
34 @ MichaĆ«l Peeters and Gilles Van Assche. For more information, feedback or
35 @ questions, please refer to our website: http://keccak.noekeon.org/
36 @
37 @ Implementation by Ronny Van Keer, hereby denoted as "the implementer".
38 @
39 @ To the extent possible under law, the implementer has waived all copyright
40 @ and related or neighboring rights to the source code in this file.
41 @ http://creativecommons.org/publicdomain/zero/1.0/
42
43 .text
44
45 .syntax unified
46 .fpu neon
47 .arm
48
49
50 .extern _gcry_keccak_round_consts_64bit;
51
52 #ifdef __PIC__
53 #  define GET_DATA_POINTER(reg, name, rtmp) \
54                 ldr reg, 1f; \
55                 ldr rtmp, 2f; \
56                 b 3f; \
57         1:      .word _GLOBAL_OFFSET_TABLE_-(3f+8); \
58         2:      .word name(GOT); \
59         3:      add reg, pc, reg; \
60                 ldr reg, [reg, rtmp];
61 #else
62 #  define GET_DATA_POINTER(reg, name, rtmp) ldr reg, =name
63 #endif
64
65
66 @//  --- offsets in state
67 .equ Aba, 0*8
68 .equ Aga, 1*8
69 .equ Aka, 2*8
70 .equ Ama, 3*8
71 .equ Asa, 4*8
72
73 @// --- macros
74
75 .macro    KeccakThetaRhoPiChiIota argA1, argA2, argA3, argA4, argA5
76
77     @Prepare Theta
78     @Ca = Aba^Aga^Aka^Ama^Asa@
79     @Ce = Abe^Age^Ake^Ame^Ase@
80     @Ci = Abi^Agi^Aki^Ami^Asi@
81     @Co = Abo^Ago^Ako^Amo^Aso@
82     @Cu = Abu^Agu^Aku^Amu^Asu@
83     @De = Ca^ROL64(Ci, 1)@
84     @Di = Ce^ROL64(Co, 1)@
85     @Do = Ci^ROL64(Cu, 1)@
86     @Du = Co^ROL64(Ca, 1)@
87     @Da = Cu^ROL64(Ce, 1)@
88
89     veor.64 q4, q6, q7
90     veor.64 q5, q9, q10
91     veor.64 d8,  d8,   d9
92     veor.64 d10,  d10,   d11
93     veor.64 d1,  d8,   d16
94     veor.64 d2,  d10,   d17
95
96     veor.64 q4, q11, q12
97     veor.64 q5, q14, q15
98     veor.64 d8,  d8,   d9
99     veor.64 d10,  d10,   d11
100     veor.64 d3,  d8,   d26
101
102     vadd.u64 q4, q1, q1
103     veor.64 d4,  d10,   d27
104     vmov.64  d0, d5
105     vsri.64 q4, q1, #63
106
107     vadd.u64 q5, q2, q2
108     veor.64 q4, q4, q0
109     vsri.64 q5, q2, #63
110     vadd.u64 d7, d1, d1
111     veor.64 \argA2, \argA2, d8
112     veor.64 q5, q5, q1
113
114     vsri.64 d7, d1, #63
115     vshl.u64 d1, \argA2, #44
116     veor.64 \argA3, \argA3, d9
117     veor.64 d7, d7, d4
118
119     @Ba = argA1^Da@
120     @Be = ROL64((argA2^De), 44)@
121     @Bi = ROL64((argA3^Di), 43)@
122     @Bo = ROL64((argA4^Do), 21)@
123     @Bu = ROL64((argA5^Du), 14)@
124     @argA2 =   Be ^((~Bi)& Bo )@
125     @argA3 =   Bi ^((~Bo)& Bu )@
126     @argA4 =   Bo ^((~Bu)& Ba )@
127     @argA5 =   Bu ^((~Ba)& Be )@
128     @argA1 =   Ba ^((~Be)& Bi )@ argA1 ^= KeccakF1600RoundConstants[i+round]@
129     vsri.64 d1, \argA2, #64-44
130     vshl.u64 d2, \argA3, #43
131     vldr.64 d0, [sp, #\argA1]
132     veor.64 \argA4, \argA4, d10
133     vsri.64 d2, \argA3, #64-43
134     vshl.u64 d3, \argA4, #21
135     veor.64 \argA5, \argA5, d11
136     veor.64 d0, d0, d7
137     vsri.64 d3, \argA4, #64-21
138     vbic.64   d5, d2, d1
139     vshl.u64 d4, \argA5, #14
140     vbic.64   \argA2, d3, d2
141     vld1.64   d6, [ip]!
142     veor.64   d5, d0
143     vsri.64 d4, \argA5, #64-14
144     veor.64   d5, d6
145     vbic.64   \argA5, d1, d0
146     vbic.64   \argA3, d4, d3
147     vbic.64   \argA4, d0, d4
148     veor.64   \argA2, d1
149     vstr.64   d5, [sp, #\argA1]
150     veor.64   \argA3, d2
151     veor.64   \argA4, d3
152     veor.64   \argA5, d4
153
154     .endm
155
156 .macro    KeccakThetaRhoPiChi1   argA1, argA2, argA3, argA4, argA5
157
158     @d2 = ROL64((argA1^Da), 3)@
159     @d3 = ROL64((argA2^De), 45)@
160     @d4 = ROL64((argA3^Di), 61)@
161     @d0 = ROL64((argA4^Do), 28)@
162     @d1 = ROL64((argA5^Du), 20)@
163     @argA1 =   Ba ^((~Be)&  Bi )@ Ca ^= argA1@
164     @argA2 =   Be ^((~Bi)&  Bo )@
165     @argA3 =   Bi ^((~Bo)&  Bu )@
166     @argA4 =   Bo ^((~Bu)&  Ba )@
167     @argA5 =   Bu ^((~Ba)&  Be )@
168
169     veor.64 \argA2, \argA2, d8
170     veor.64 \argA3, \argA3, d9
171     vshl.u64  d3, \argA2, #45
172     vldr.64 d6, [sp, #\argA1]
173     vshl.u64  d4, \argA3, #61
174     veor.64 \argA4, \argA4, d10
175     vsri.64  d3, \argA2, #64-45
176     veor.64 \argA5, \argA5, d11
177     vsri.64  d4, \argA3, #64-61
178     vshl.u64  d0, \argA4, #28
179     veor.64 d6, d6, d7
180     vshl.u64  d1, \argA5, #20
181     vbic.64   \argA3, d4, d3
182     vsri.64  d0, \argA4, #64-28
183     vbic.64   \argA4, d0, d4
184     vshl.u64  d2, d6, #3
185     vsri.64  d1, \argA5, #64-20
186     veor.64   \argA4, d3
187     vsri.64  d2, d6, #64-3
188     vbic.64   \argA5, d1, d0
189     vbic.64   d6, d2, d1
190     vbic.64   \argA2, d3, d2
191     veor.64   d6, d0
192     veor.64   \argA2, d1
193     vstr.64   d6, [sp, #\argA1]
194     veor.64   \argA3, d2
195     veor.64  d5, d6
196     veor.64   \argA5, d4
197
198     .endm
199
200 .macro    KeccakThetaRhoPiChi2 argA1, argA2, argA3, argA4, argA5
201
202     @d4 = ROL64((argA1^Da), 18)@
203     @d0 = ROL64((argA2^De), 1)@
204     @d1 = ROL64((argA3^Di), 6)@
205     @d2 = ROL64((argA4^Do), 25)@
206     @d3 = ROL64((argA5^Du), 8)@
207     @argA1 =   Ba ^((~Be)&  Bi )@ Ca ^= argA1@
208     @argA2 =   Be ^((~Bi)&  Bo )@
209     @argA3 =   Bi ^((~Bo)&  Bu )@
210     @argA4 =   Bo ^((~Bu)&  Ba )@
211     @argA5 =   Bu ^((~Ba)&  Be )@
212
213     veor.64 \argA3, \argA3, d9
214     veor.64 \argA4, \argA4, d10
215     vshl.u64  d1, \argA3, #6
216     vldr.64 d6, [sp, #\argA1]
217     vshl.u64  d2, \argA4, #25
218     veor.64 \argA5, \argA5, d11
219     vsri.64  d1, \argA3, #64-6
220     veor.64 \argA2, \argA2, d8
221     vsri.64  d2, \argA4, #64-25
222     vext.8  d3, \argA5, \argA5, #7
223     veor.64 d6, d6, d7
224     vbic.64  \argA3, d2, d1
225     vadd.u64  d0, \argA2, \argA2
226     vbic.64   \argA4, d3, d2
227     vsri.64  d0, \argA2, #64-1
228     vshl.u64  d4, d6, #18
229     veor.64  \argA2, d1, \argA4
230     veor.64  \argA3, d0
231     vsri.64  d4, d6, #64-18
232     vstr.64   \argA3, [sp, #\argA1]
233     veor.64  d5, \argA3
234     vbic.64   \argA5, d1, d0
235     vbic.64   \argA3, d4, d3
236     vbic.64   \argA4, d0, d4
237     veor.64   \argA3, d2
238     veor.64   \argA4, d3
239     veor.64   \argA5, d4
240
241     .endm
242
243 .macro    KeccakThetaRhoPiChi3 argA1, argA2, argA3, argA4, argA5
244
245     @d1 = ROL64((argA1^Da), 36)@
246     @d2 = ROL64((argA2^De), 10)@
247     @d3 = ROL64((argA3^Di), 15)@
248     @d4 = ROL64((argA4^Do), 56)@
249     @d0 = ROL64((argA5^Du), 27)@
250     @argA1 =   Ba ^((~Be)&  Bi )@ Ca ^= argA1@
251     @argA2 =   Be ^((~Bi)&  Bo )@
252     @argA3 =   Bi ^((~Bo)&  Bu )@
253     @argA4 =   Bo ^((~Bu)&  Ba )@
254     @argA5 =   Bu ^((~Ba)&  Be )@
255
256     veor.64 \argA2, \argA2, d8
257     veor.64 \argA3, \argA3, d9
258     vshl.u64  d2, \argA2, #10
259     vldr.64 d6, [sp, #\argA1]
260     vshl.u64  d3, \argA3, #15
261     veor.64 \argA4, \argA4, d10
262     vsri.64  d2, \argA2, #64-10
263     vsri.64  d3, \argA3, #64-15
264     veor.64 \argA5, \argA5, d11
265     vext.8  d4, \argA4, \argA4, #1
266     vbic.64   \argA2, d3, d2
267     vshl.u64  d0, \argA5, #27
268     veor.64 d6, d6, d7
269     vbic.64   \argA3, d4, d3
270     vsri.64  d0, \argA5, #64-27
271     vshl.u64  d1, d6, #36
272     veor.64   \argA3, d2
273     vbic.64   \argA4, d0, d4
274     vsri.64  d1, d6, #64-36
275
276     veor.64   \argA4, d3
277     vbic.64   d6, d2, d1
278     vbic.64   \argA5, d1, d0
279     veor.64   d6, d0
280     veor.64   \argA2, d1
281     vstr.64   d6, [sp, #\argA1]
282     veor.64  d5, d6
283     veor.64   \argA5, d4
284
285     .endm
286
287 .macro    KeccakThetaRhoPiChi4 argA1, argA2, argA3, argA4, argA5
288
289     @d3 = ROL64((argA1^Da), 41)@
290     @d4 = ROL64((argA2^De), 2)@
291     @d0 = ROL64((argA3^Di), 62)@
292     @d1 = ROL64((argA4^Do), 55)@
293     @d2 = ROL64((argA5^Du), 39)@
294     @argA1 =   Ba ^((~Be)&  Bi )@ Ca ^= argA1@
295     @argA2 =   Be ^((~Bi)&  Bo )@
296     @argA3 =   Bi ^((~Bo)&  Bu )@
297     @argA4 =   Bo ^((~Bu)&  Ba )@
298     @argA5 =   Bu ^((~Ba)&  Be )@
299
300     veor.64 \argA2, \argA2, d8
301     veor.64 \argA3, \argA3, d9
302     vshl.u64  d4, \argA2, #2
303     veor.64 \argA5, \argA5, d11
304     vshl.u64  d0, \argA3, #62
305     vldr.64 d6, [sp, #\argA1]
306     vsri.64  d4, \argA2, #64-2
307     veor.64 \argA4, \argA4, d10
308     vsri.64  d0, \argA3, #64-62
309
310     vshl.u64  d1, \argA4, #55
311     veor.64 d6, d6, d7
312     vshl.u64  d2, \argA5, #39
313     vsri.64  d1, \argA4, #64-55
314     vbic.64  \argA4, d0, d4
315     vsri.64  d2, \argA5, #64-39
316     vbic.64  \argA2, d1, d0
317     vshl.u64  d3, d6, #41
318     veor.64  \argA5, d4, \argA2
319     vbic.64  \argA2, d2, d1
320     vsri.64  d3, d6, #64-41
321     veor.64  d6, d0, \argA2
322
323     vbic.64 \argA2, d3, d2
324     vbic.64 \argA3, d4, d3
325     veor.64 \argA2, d1
326     vstr.64 d6, [sp, #\argA1]
327     veor.64 d5, d6
328     veor.64 \argA3, d2
329     veor.64 \argA4, d3
330
331     .endm
332
333
334 @// --- code
335
336 @not callable from C!
337 .p2align 3
338 .type  KeccakF_armv7a_neon_asm,%function;
339 KeccakF_armv7a_neon_asm:  @
340
341 .LroundLoop:
342
343     KeccakThetaRhoPiChiIota  Aba, d13, d19, d25, d31
344     KeccakThetaRhoPiChi1    Aka, d15, d21, d22, d28
345     KeccakThetaRhoPiChi2    Asa, d12, d18, d24, d30
346     KeccakThetaRhoPiChi3    Aga, d14, d20, d26, d27
347     KeccakThetaRhoPiChi4    Ama, d16, d17, d23, d29
348
349     KeccakThetaRhoPiChiIota  Aba, d15, d18, d26, d29
350     KeccakThetaRhoPiChi1    Asa, d14, d17, d25, d28
351     KeccakThetaRhoPiChi2    Ama, d13, d21, d24, d27
352     KeccakThetaRhoPiChi3    Aka, d12, d20, d23, d31
353     KeccakThetaRhoPiChi4    Aga, d16, d19, d22, d30
354
355     KeccakThetaRhoPiChiIota Aba, d14, d21, d23, d30
356     KeccakThetaRhoPiChi1    Ama, d12, d19, d26, d28
357     KeccakThetaRhoPiChi2    Aga, d15, d17, d24, d31
358     KeccakThetaRhoPiChi3    Asa, d13, d20, d22, d29
359     KeccakThetaRhoPiChi4    Aka, d16, d18, d25, d27
360
361     KeccakThetaRhoPiChiIota Aba, d12, d17, d22, d27
362     KeccakThetaRhoPiChi1    Aga, d13, d18, d23, d28
363     KeccakThetaRhoPiChi2    Aka, d14, d19, d24, d29
364     ldr    r0, [ip]
365     KeccakThetaRhoPiChi3    Ama, d15, d20, d25, d30
366     cmp    r0, #0xFFFFFFFF
367     KeccakThetaRhoPiChi4    Asa, d16, d21, d26, d31
368
369     bne    .LroundLoop
370     sub    ip, #(8*24)
371     bx    lr
372 .p2align 2
373 .ltorg
374 .size KeccakF_armv7a_neon_asm,.-KeccakF_armv7a_neon_asm;
375
376
377 @//unsigned _gcry_keccak_permute_armv7_neon(u64 *state)  callable from C
378 .p2align 3
379 .global   _gcry_keccak_permute_armv7_neon
380 .type  _gcry_keccak_permute_armv7_neon,%function;
381 _gcry_keccak_permute_armv7_neon:
382
383     push   {ip, lr}
384     vpush  {q4-q7}
385     sub    sp,sp, #5*8
386
387     vldr.64  d0,  [r0, #0*8]
388     vldr.64  d12, [r0, #1*8]
389     vldr.64  d17, [r0, #2*8]
390     vldr.64  d22, [r0, #3*8]
391     vldr.64  d27, [r0, #4*8]
392
393     GET_DATA_POINTER(ip, _gcry_keccak_round_consts_64bit, lr);
394
395     vldr.64  d1,  [r0, #5*8]
396     vldr.64  d13, [r0, #6*8]
397     vldr.64  d18, [r0, #7*8]
398     vldr.64  d23, [r0, #8*8]
399     vldr.64  d28, [r0, #9*8]
400
401     vldr.64  d2,  [r0, #10*8]
402     vldr.64  d14, [r0, #11*8]
403     vldr.64  d19, [r0, #12*8]
404     vldr.64  d24, [r0, #13*8]
405     vldr.64  d29, [r0, #14*8]
406
407     vldr.64  d3,  [r0, #15*8]
408     vldr.64  d15, [r0, #16*8]
409     vldr.64  d20, [r0, #17*8]
410     vldr.64  d25, [r0, #18*8]
411     vldr.64  d30, [r0, #19*8]
412
413     vldr.64  d4,  [r0, #20*8]
414     vldr.64  d16, [r0, #21*8]
415     vldr.64  d21, [r0, #22*8]
416     vldr.64  d26, [r0, #23*8]
417     vldr.64  d31, [r0, #24*8]
418
419     vstr.64  d0, [sp, #Aba]
420     vstr.64  d1, [sp, #Aga]
421     veor.64 q0, q0, q1
422     vstr.64  d2, [sp, #Aka]
423     veor.64 d5, d0,  d1
424     vstr.64  d3, [sp, #Ama]
425     mov      r1, r0
426     vstr.64  d4, [sp, #Asa]
427     veor.64 d5, d5,  d4
428
429     bl KeccakF_armv7a_neon_asm
430
431     vpop.64  { d0- d4 }
432
433     vstr.64  d0,  [r1, #0*8]
434     vstr.64  d12, [r1, #1*8]
435     vstr.64  d17, [r1, #2*8]
436     vstr.64  d22, [r1, #3*8]
437     vstr.64  d27, [r1, #4*8]
438
439     vstr.64  d1,  [r1, #5*8]
440     vstr.64  d13, [r1, #6*8]
441     vstr.64  d18, [r1, #7*8]
442     vstr.64  d23, [r1, #8*8]
443     vstr.64  d28, [r1, #9*8]
444
445     vstr.64  d2,  [r1, #10*8]
446     vstr.64  d14, [r1, #11*8]
447     vstr.64  d19, [r1, #12*8]
448     vstr.64  d24, [r1, #13*8]
449     vstr.64  d29, [r1, #14*8]
450
451     vstr.64  d3,  [r1, #15*8]
452     vstr.64  d15, [r1, #16*8]
453     vstr.64  d20, [r1, #17*8]
454     vstr.64  d25, [r1, #18*8]
455     vstr.64  d30, [r1, #19*8]
456
457     vstr.64  d4,  [r1, #20*8]
458     vstr.64  d16, [r1, #21*8]
459     vstr.64  d21, [r1, #22*8]
460     vstr.64  d26, [r1, #23*8]
461     vstr.64  d31, [r1, #24*8]
462
463     mov   r0, #112
464     vpop  {q4-q7}
465     pop   {ip, pc}
466 .p2align 2
467 .ltorg
468 .size _gcry_keccak_permute_armv7_neon,.-_gcry_keccak_permute_armv7_neon;
469
470 @//unsigned _gcry_keccak_permute_armv7_neon(u64 *state, @r4
471 @                                           int pos,    @r1
472 @                                           const byte *lanes,   @r2
473 @                                           unsigned int nlanes, @r3
474 @                                           int blocklanes) @ r5 callable from C
475 .p2align 3
476 .global   _gcry_keccak_absorb_lanes64_armv7_neon
477 .type  _gcry_keccak_absorb_lanes64_armv7_neon,%function;
478 _gcry_keccak_absorb_lanes64_armv7_neon:
479
480     cmp    r3, #0       @ nlanes == 0
481     itt eq
482     moveq  r0, #0
483     bxeq   lr
484
485     push   {r4-r5, ip, lr}
486     beq    .Lout
487     mov    r4, r0
488     ldr    r5, [sp, #(4*4)]
489     vpush  {q4-q7}
490
491     @ load state
492     vldr.64  d0,  [r4, #0*8]
493     vldr.64  d12, [r4, #1*8]
494     vldr.64  d17, [r4, #2*8]
495     vldr.64  d22, [r4, #3*8]
496     vldr.64  d27, [r4, #4*8]
497
498     GET_DATA_POINTER(ip, _gcry_keccak_round_consts_64bit, lr);
499
500     vldr.64  d1,  [r4, #5*8]
501     vldr.64  d13, [r4, #6*8]
502     vldr.64  d18, [r4, #7*8]
503     vldr.64  d23, [r4, #8*8]
504     vldr.64  d28, [r4, #9*8]
505
506     vldr.64  d2,  [r4, #10*8]
507     vldr.64  d14, [r4, #11*8]
508     vldr.64  d19, [r4, #12*8]
509     vldr.64  d24, [r4, #13*8]
510     vldr.64  d29, [r4, #14*8]
511
512     vldr.64  d3,  [r4, #15*8]
513     vldr.64  d15, [r4, #16*8]
514     vldr.64  d20, [r4, #17*8]
515     vldr.64  d25, [r4, #18*8]
516     vldr.64  d30, [r4, #19*8]
517
518     vldr.64  d4,  [r4, #20*8]
519     vldr.64  d16, [r4, #21*8]
520     vldr.64  d21, [r4, #22*8]
521     vldr.64  d26, [r4, #23*8]
522     vldr.64  d31, [r4, #24*8]
523
524 .Lmain_loop:
525
526     @ detect absorb mode (full blocks vs lanes)
527
528     cmp r1, #0          @ pos != 0
529     bne .Llanes_loop
530
531 .Lmain_loop_pos0:
532
533     @ full blocks mode
534
535     @ switch (blocksize)
536     cmp r5, #21
537     beq .Lfull_block_21
538     cmp r5, #18
539     beq .Lfull_block_18
540     cmp r5, #17
541     beq .Lfull_block_17
542     cmp r5, #13
543     beq .Lfull_block_13
544     cmp r5, #9
545     beq .Lfull_block_9
546
547     @ unknown blocksize
548     b .Llanes_loop
549
550 .Lfull_block_21:
551
552     @ SHAKE128
553
554     cmp r3, #21         @ nlanes < blocklanes
555     blo .Llanes_loop
556
557     sub    sp,sp, #5*8
558
559     vld1.64 {d5-d8}, [r2]!
560     veor d0,  d5
561     vld1.64 {d9-d11}, [r2]!
562     veor d12, d6
563     veor d17, d7
564     veor d22, d8
565     vld1.64 {d5-d8}, [r2]!
566     veor d27, d9
567
568     veor d1,  d10
569     veor d13, d11
570     vld1.64 {d9-d11}, [r2]!
571     veor d18, d5
572     veor d23, d6
573     veor d28, d7
574
575     veor d2,  d8
576     vld1.64 {d5-d8}, [r2]!
577     veor d14, d9
578     veor d19, d10
579     veor d24, d11
580     vld1.64 {d9-d11}, [r2]!
581     veor d29, d5
582
583     veor d3,  d6
584     veor d15, d7
585     veor d20, d8
586     veor d25, d9
587     veor d30, d10
588
589     veor d4,  d11
590
591     vstr.64  d0, [sp, #Aba]
592     vstr.64  d1, [sp, #Aga]
593     veor.64 q0, q0, q1
594     vstr.64  d2, [sp, #Aka]
595     veor.64 d5, d0,  d1
596     vstr.64  d3, [sp, #Ama]
597     vstr.64  d4, [sp, #Asa]
598     veor.64 d5, d5,  d4
599
600     bl KeccakF_armv7a_neon_asm
601
602     subs r3, #21        @ nlanes -= 21
603     vpop.64  { d0-d4 }
604
605     beq .Ldone
606
607     b .Lfull_block_21
608
609 .Lfull_block_18:
610
611     @ SHA3-224
612
613     cmp r3, #18         @ nlanes < blocklanes
614     blo .Llanes_loop
615
616     sub    sp,sp, #5*8
617
618     vld1.64 {d5-d8}, [r2]!
619     veor d0,  d5
620     vld1.64 {d9-d11}, [r2]!
621     veor d12, d6
622     veor d17, d7
623     veor d22, d8
624     vld1.64 {d5-d8}, [r2]!
625     veor d27, d9
626
627     veor d1,  d10
628     veor d13, d11
629     vld1.64 {d9-d11}, [r2]!
630     veor d18, d5
631     veor d23, d6
632     veor d28, d7
633
634     veor d2,  d8
635     vld1.64 {d5-d8}, [r2]!
636     veor d14, d9
637     veor d19, d10
638     veor d24, d11
639     veor d29, d5
640
641     veor d3,  d6
642     veor d15, d7
643     veor d20, d8
644
645     vstr.64  d0, [sp, #Aba]
646     vstr.64  d1, [sp, #Aga]
647     veor.64 q0, q0, q1
648     vstr.64  d2, [sp, #Aka]
649     veor.64 d5, d0,  d1
650     vstr.64  d3, [sp, #Ama]
651     vstr.64  d4, [sp, #Asa]
652     veor.64 d5, d5,  d4
653
654     bl KeccakF_armv7a_neon_asm
655
656     subs r3, #18        @ nlanes -= 18
657     vpop.64  { d0-d4 }
658
659     beq .Ldone
660
661     b .Lfull_block_18
662
663 .Lfull_block_17:
664
665     @ SHA3-256 & SHAKE256
666
667     cmp r3, #17         @ nlanes < blocklanes
668     blo .Llanes_loop
669
670     sub    sp,sp, #5*8
671
672     vld1.64 {d5-d8}, [r2]!
673     veor d0,  d5
674     vld1.64 {d9-d11}, [r2]!
675     veor d12, d6
676     veor d17, d7
677     veor d22, d8
678     vld1.64 {d5-d8}, [r2]!
679     veor d27, d9
680
681     veor d1,  d10
682     veor d13, d11
683     vld1.64 {d9-d11}, [r2]!
684     veor d18, d5
685     veor d23, d6
686     veor d28, d7
687
688     veor d2,  d8
689     vld1.64 {d5-d7}, [r2]!
690     veor d14, d9
691     veor d19, d10
692     veor d24, d11
693     veor d29, d5
694
695     veor d3,  d6
696     veor d15, d7
697
698     vstr.64  d0, [sp, #Aba]
699     vstr.64  d1, [sp, #Aga]
700     veor.64 q0, q0, q1
701     vstr.64  d2, [sp, #Aka]
702     veor.64 d5, d0,  d1
703     vstr.64  d3, [sp, #Ama]
704     vstr.64  d4, [sp, #Asa]
705     veor.64 d5, d5,  d4
706
707     bl KeccakF_armv7a_neon_asm
708
709     subs r3, #17        @ nlanes -= 17
710     vpop.64  { d0-d4 }
711
712     beq .Ldone
713
714     b .Lfull_block_17
715
716 .Lfull_block_13:
717
718     @ SHA3-384
719
720     cmp r3, #13         @ nlanes < blocklanes
721     blo .Llanes_loop
722
723     sub    sp,sp, #5*8
724
725     vld1.64 {d5-d8}, [r2]!
726     veor d0,  d5
727     vld1.64 {d9-d11}, [r2]!
728     veor d12, d6
729     veor d17, d7
730     veor d22, d8
731     vld1.64 {d5-d8}, [r2]!
732     veor d27, d9
733
734     veor d1,  d10
735     veor d13, d11
736     vld1.64 {d9-d10}, [r2]!
737     veor d18, d5
738     veor d23, d6
739     veor d28, d7
740
741     veor d2,  d8
742     veor d14, d9
743     veor d19, d10
744
745     vstr.64  d0, [sp, #Aba]
746     vstr.64  d1, [sp, #Aga]
747     veor.64 q0, q0, q1
748     vstr.64  d2, [sp, #Aka]
749     veor.64 d5, d0,  d1
750     vstr.64  d3, [sp, #Ama]
751     vstr.64  d4, [sp, #Asa]
752     veor.64 d5, d5,  d4
753
754     bl KeccakF_armv7a_neon_asm
755
756     subs r3, #13        @ nlanes -= 13
757     vpop.64  { d0-d4 }
758
759     beq .Ldone
760
761     b .Lfull_block_13
762
763 .Lfull_block_9:
764
765     @ SHA3-512
766
767     cmp r3, #9          @ nlanes < blocklanes
768     blo .Llanes_loop
769
770     sub    sp,sp, #5*8
771
772     vld1.64 {d5-d8}, [r2]!
773     veor d0,  d5
774     vld1.64 {d9-d11}, [r2]!
775     veor d12, d6
776     veor d17, d7
777     veor d22, d8
778     vld1.64 {d5-d6}, [r2]!
779     veor d27, d9
780
781     veor d1,  d10
782     veor d13, d11
783     veor d18, d5
784     veor d23, d6
785
786     vstr.64  d0, [sp, #Aba]
787     vstr.64  d1, [sp, #Aga]
788     veor.64 q0, q0, q1
789     vstr.64  d2, [sp, #Aka]
790     veor.64 d5, d0,  d1
791     vstr.64  d3, [sp, #Ama]
792     vstr.64  d4, [sp, #Asa]
793     veor.64 d5, d5,  d4
794
795     bl KeccakF_armv7a_neon_asm
796
797     subs r3, #9         @ nlanes -= 9
798     vpop.64  { d0-d4 }
799
800     beq .Ldone
801
802     b .Lfull_block_9
803
804 .Llanes_loop:
805
806     @ per-lane mode
807
808     @ switch (pos)
809     ldrb r0, [pc, r1]
810     add pc, pc, r0, lsl #2
811 .Lswitch_table:
812     .byte (.Llane0-.Lswitch_table-4)/4
813     .byte (.Llane1-.Lswitch_table-4)/4
814     .byte (.Llane2-.Lswitch_table-4)/4
815     .byte (.Llane3-.Lswitch_table-4)/4
816     .byte (.Llane4-.Lswitch_table-4)/4
817     .byte (.Llane5-.Lswitch_table-4)/4
818     .byte (.Llane6-.Lswitch_table-4)/4
819     .byte (.Llane7-.Lswitch_table-4)/4
820     .byte (.Llane8-.Lswitch_table-4)/4
821     .byte (.Llane9-.Lswitch_table-4)/4
822     .byte (.Llane10-.Lswitch_table-4)/4
823     .byte (.Llane11-.Lswitch_table-4)/4
824     .byte (.Llane12-.Lswitch_table-4)/4
825     .byte (.Llane13-.Lswitch_table-4)/4
826     .byte (.Llane14-.Lswitch_table-4)/4
827     .byte (.Llane15-.Lswitch_table-4)/4
828     .byte (.Llane16-.Lswitch_table-4)/4
829     .byte (.Llane17-.Lswitch_table-4)/4
830     .byte (.Llane18-.Lswitch_table-4)/4
831     .byte (.Llane19-.Lswitch_table-4)/4
832     .byte (.Llane20-.Lswitch_table-4)/4
833     .byte (.Llane21-.Lswitch_table-4)/4
834     .byte (.Llane22-.Lswitch_table-4)/4
835     .byte (.Llane23-.Lswitch_table-4)/4
836     .byte (.Llane24-.Lswitch_table-4)/4
837 .p2align 2
838
839 #define ABSORB_LANE(label, vreg) \
840     label: \
841       add     r1, #1; \
842       vld1.64 d5, [r2]!; \
843       cmp     r1, r5; /* pos == blocklanes */ \
844       veor    vreg, vreg, d5; \
845       beq     .Llanes_permute; \
846       subs    r3, #1; \
847       beq     .Ldone;
848
849     ABSORB_LANE(.Llane0, d0)
850     ABSORB_LANE(.Llane1, d12)
851     ABSORB_LANE(.Llane2, d17)
852     ABSORB_LANE(.Llane3, d22)
853     ABSORB_LANE(.Llane4, d27)
854
855     ABSORB_LANE(.Llane5, d1)
856     ABSORB_LANE(.Llane6, d13)
857     ABSORB_LANE(.Llane7, d18)
858     ABSORB_LANE(.Llane8, d23)
859     ABSORB_LANE(.Llane9, d28)
860
861     ABSORB_LANE(.Llane10, d2)
862     ABSORB_LANE(.Llane11, d14)
863     ABSORB_LANE(.Llane12, d19)
864     ABSORB_LANE(.Llane13, d24)
865     ABSORB_LANE(.Llane14, d29)
866
867     ABSORB_LANE(.Llane15, d3)
868     ABSORB_LANE(.Llane16, d15)
869     ABSORB_LANE(.Llane17, d20)
870     ABSORB_LANE(.Llane18, d25)
871     ABSORB_LANE(.Llane19, d30)
872
873     ABSORB_LANE(.Llane20, d4)
874     ABSORB_LANE(.Llane21, d16)
875     ABSORB_LANE(.Llane22, d21)
876     ABSORB_LANE(.Llane23, d26)
877     ABSORB_LANE(.Llane24, d31)
878
879     b .Llanes_loop
880
881 .Llanes_permute:
882
883     sub    sp,sp, #5*8
884     vstr.64  d0, [sp, #Aba]
885     vstr.64  d1, [sp, #Aga]
886     veor.64 q0, q0, q1
887     vstr.64  d2, [sp, #Aka]
888     veor.64 d5, d0,  d1
889     vstr.64  d3, [sp, #Ama]
890     vstr.64  d4, [sp, #Asa]
891     veor.64 d5, d5,  d4
892
893     bl KeccakF_armv7a_neon_asm
894
895     mov  r1, #0   @ pos <= 0
896     subs r3, #1
897
898     vpop.64  { d0-d4 }
899
900     beq  .Ldone
901
902     b .Lmain_loop_pos0
903
904 .Ldone:
905
906     @ save state
907     vstr.64  d0,  [r4, #0*8]
908     vstr.64  d12, [r4, #1*8]
909     vstr.64  d17, [r4, #2*8]
910     vstr.64  d22, [r4, #3*8]
911     vstr.64  d27, [r4, #4*8]
912
913     vstr.64  d1,  [r4, #5*8]
914     vstr.64  d13, [r4, #6*8]
915     vstr.64  d18, [r4, #7*8]
916     vstr.64  d23, [r4, #8*8]
917     vstr.64  d28, [r4, #9*8]
918
919     vstr.64  d2,  [r4, #10*8]
920     vstr.64  d14, [r4, #11*8]
921     vstr.64  d19, [r4, #12*8]
922     vstr.64  d24, [r4, #13*8]
923     vstr.64  d29, [r4, #14*8]
924
925     vstr.64  d3,  [r4, #15*8]
926     vstr.64  d15, [r4, #16*8]
927     vstr.64  d20, [r4, #17*8]
928     vstr.64  d25, [r4, #18*8]
929     vstr.64  d30, [r4, #19*8]
930
931     vstr.64  d4,  [r4, #20*8]
932     vstr.64  d16, [r4, #21*8]
933     vstr.64  d21, [r4, #22*8]
934     vstr.64  d26, [r4, #23*8]
935     vstr.64  d31, [r4, #24*8]
936
937     mov   r0, #120
938     vpop  {q4-q7}
939 .Lout:
940     pop   {r4-r5, ip, pc}
941 .p2align 2
942 .ltorg
943 .size _gcry_keccak_absorb_lanes64_armv7_neon,.-_gcry_keccak_absorb_lanes64_armv7_neon;
944
945 #endif