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;
339KeccakF_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
946