ecc: Fix ec_mulm_25519.
[libgcrypt.git] / cipher / sha1-armv7-neon.S
1 /* sha1-armv7-neon.S - ARM/NEON accelerated SHA-1 transform function
2  * Copyright (C) 2013-2014 Jussi Kivilinna <jussi.kivilinna@iki.fi>
3  *
4  * Based on sha1.c:
5  *  Copyright (C) 1998, 2001, 2002, 2003, 2008 Free Software Foundation, Inc.
6  *
7  * This file is part of Libgcrypt.
8  *
9  * Libgcrypt is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU Lesser General Public License as
11  * published by the Free Software Foundation; either version 2.1 of
12  * the License, or (at your option) any later version.
13  *
14  * Libgcrypt is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this program; if not, see <http://www.gnu.org/licenses/>.
21  */
22
23 #include <config.h>
24
25 #if defined(HAVE_ARM_ARCH_V6) && defined(__ARMEL__) && \
26     defined(HAVE_COMPATIBLE_GCC_ARM_PLATFORM_AS) && \
27     defined(HAVE_GCC_INLINE_ASM_NEON) && defined(USE_SHA1)
28
29 .syntax unified
30 .fpu neon
31 .arm
32
33 .text
34
35 #ifdef __PIC__
36 #  define GET_DATA_POINTER(reg, name, rtmp) \
37                 ldr reg, 1f; \
38                 ldr rtmp, 2f; \
39                 b 3f; \
40         1:      .word _GLOBAL_OFFSET_TABLE_-(3f+8); \
41         2:      .word name(GOT); \
42         3:      add reg, pc, reg; \
43                 ldr reg, [reg, rtmp];
44 #else
45 #  define GET_DATA_POINTER(reg, name, rtmp) ldr reg, =name
46 #endif
47
48 /* Context structure */
49
50 #define state_h0 0
51 #define state_h1 4
52 #define state_h2 8
53 #define state_h3 12
54 #define state_h4 16
55
56
57 /* Constants */
58
59 #define K1  0x5A827999
60 #define K2  0x6ED9EBA1
61 #define K3  0x8F1BBCDC
62 #define K4  0xCA62C1D6
63 .align 4
64 gcry_sha1_armv7_neon_K_VEC:
65 .LK_VEC:
66 .LK1:   .long K1, K1, K1, K1
67 .LK2:   .long K2, K2, K2, K2
68 .LK3:   .long K3, K3, K3, K3
69 .LK4:   .long K4, K4, K4, K4
70
71
72 /* Register macros */
73
74 #define RSTATE r0
75 #define RDATA r1
76 #define RNBLKS r2
77 #define ROLDSTACK r3
78 #define RWK lr
79
80 #define _a r4
81 #define _b r5
82 #define _c r6
83 #define _d r7
84 #define _e r8
85
86 #define RT0 r9
87 #define RT1 r10
88 #define RT2 r11
89 #define RT3 r12
90
91 #define W0 q0
92 #define W1 q1
93 #define W2 q2
94 #define W3 q3
95 #define W4 q4
96 #define W5 q5
97 #define W6 q6
98 #define W7 q7
99
100 #define tmp0 q8
101 #define tmp1 q9
102 #define tmp2 q10
103 #define tmp3 q11
104
105 #define qK1 q12
106 #define qK2 q13
107 #define qK3 q14
108 #define qK4 q15
109
110
111 /* Round function macros. */
112
113 #define WK_offs(i) (((i) & 15) * 4)
114
115 #define _R_F1(a,b,c,d,e,i,pre1,pre2,pre3,i16,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28) \
116         ldr RT3, [sp, WK_offs(i)]; \
117                 pre1(i16,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28); \
118         bic RT0, d, b; \
119         add e, e, a, ror #(32 - 5); \
120         and RT1, c, b; \
121                 pre2(i16,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28); \
122         add RT0, RT0, RT3; \
123         add e, e, RT1; \
124         ror b, #(32 - 30); \
125                 pre3(i16,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28); \
126         add e, e, RT0;
127
128 #define _R_F2(a,b,c,d,e,i,pre1,pre2,pre3,i16,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28) \
129         ldr RT3, [sp, WK_offs(i)]; \
130                 pre1(i16,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28); \
131         eor RT0, d, b; \
132         add e, e, a, ror #(32 - 5); \
133         eor RT0, RT0, c; \
134                 pre2(i16,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28); \
135         add e, e, RT3; \
136         ror b, #(32 - 30); \
137                 pre3(i16,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28); \
138         add e, e, RT0; \
139
140 #define _R_F3(a,b,c,d,e,i,pre1,pre2,pre3,i16,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28) \
141         ldr RT3, [sp, WK_offs(i)]; \
142                 pre1(i16,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28); \
143         eor RT0, b, c; \
144         and RT1, b, c; \
145         add e, e, a, ror #(32 - 5); \
146                 pre2(i16,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28); \
147         and RT0, RT0, d; \
148         add RT1, RT1, RT3; \
149         add e, e, RT0; \
150         ror b, #(32 - 30); \
151                 pre3(i16,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28); \
152         add e, e, RT1;
153
154 #define _R_F4(a,b,c,d,e,i,pre1,pre2,pre3,i16,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28) \
155         _R_F2(a,b,c,d,e,i,pre1,pre2,pre3,i16,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28)
156
157 #define _R(a,b,c,d,e,f,i,pre1,pre2,pre3,i16,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28) \
158         _R_##f(a,b,c,d,e,i,pre1,pre2,pre3,i16,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28)
159
160 #define R(a,b,c,d,e,f,i) \
161         _R_##f(a,b,c,d,e,i,dummy,dummy,dummy,i16,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28)
162
163 #define dummy(...)
164
165
166 /* Input expansion macros. */
167
168 /********* Precalc macros for rounds 0-15 *************************************/
169
170 #define W_PRECALC_00_15() \
171         add       RWK, sp, #(WK_offs(0));                       \
172         \
173         vld1.32   {tmp0, tmp1}, [RDATA]!;                       \
174         vrev32.8  W0, tmp0;             /* big => little */     \
175         vld1.32   {tmp2, tmp3}, [RDATA]!;                       \
176         vadd.u32  tmp0, W0, curK;                               \
177         vrev32.8  W7, tmp1;             /* big => little */     \
178         vrev32.8  W6, tmp2;             /* big => little */     \
179         vadd.u32  tmp1, W7, curK;                               \
180         vrev32.8  W5, tmp3;             /* big => little */     \
181         vadd.u32  tmp2, W6, curK;                               \
182         vst1.32   {tmp0, tmp1}, [RWK]!;                         \
183         vadd.u32  tmp3, W5, curK;                               \
184         vst1.32   {tmp2, tmp3}, [RWK];                          \
185
186 #define WPRECALC_00_15_0(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
187         vld1.32   {tmp0, tmp1}, [RDATA]!;                       \
188
189 #define WPRECALC_00_15_1(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
190         add       RWK, sp, #(WK_offs(0));                       \
191
192 #define WPRECALC_00_15_2(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
193         vrev32.8  W0, tmp0;             /* big => little */     \
194
195 #define WPRECALC_00_15_3(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
196         vld1.32   {tmp2, tmp3}, [RDATA]!;                       \
197
198 #define WPRECALC_00_15_4(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
199         vadd.u32  tmp0, W0, curK;                               \
200
201 #define WPRECALC_00_15_5(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
202         vrev32.8  W7, tmp1;             /* big => little */     \
203
204 #define WPRECALC_00_15_6(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
205         vrev32.8  W6, tmp2;             /* big => little */     \
206
207 #define WPRECALC_00_15_7(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
208         vadd.u32  tmp1, W7, curK;                               \
209
210 #define WPRECALC_00_15_8(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
211         vrev32.8  W5, tmp3;             /* big => little */     \
212
213 #define WPRECALC_00_15_9(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
214         vadd.u32  tmp2, W6, curK;                               \
215
216 #define WPRECALC_00_15_10(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
217         vst1.32   {tmp0, tmp1}, [RWK]!;                         \
218
219 #define WPRECALC_00_15_11(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
220         vadd.u32  tmp3, W5, curK;                               \
221
222 #define WPRECALC_00_15_12(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
223         vst1.32   {tmp2, tmp3}, [RWK];                          \
224
225
226 /********* Precalc macros for rounds 16-31 ************************************/
227
228 #define WPRECALC_16_31_0(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
229         veor      tmp0, tmp0;                   \
230         vext.8    W, W_m16, W_m12, #8;          \
231
232 #define WPRECALC_16_31_1(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
233         add       RWK, sp, #(WK_offs(i));       \
234         vext.8    tmp0, W_m04, tmp0, #4;        \
235
236 #define WPRECALC_16_31_2(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
237         veor      tmp0, tmp0, W_m16;            \
238         veor.32   W, W, W_m08;                  \
239
240 #define WPRECALC_16_31_3(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
241         veor      tmp1, tmp1;                   \
242         veor      W, W, tmp0;                   \
243
244 #define WPRECALC_16_31_4(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
245         vshl.u32  tmp0, W, #1;                  \
246
247 #define WPRECALC_16_31_5(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
248         vext.8    tmp1, tmp1, W, #(16-12);      \
249         vshr.u32  W, W, #31;                    \
250
251 #define WPRECALC_16_31_6(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
252         vorr      tmp0, tmp0, W;                \
253         vshr.u32  W, tmp1, #30;                 \
254
255 #define WPRECALC_16_31_7(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
256         vshl.u32  tmp1, tmp1, #2;               \
257
258 #define WPRECALC_16_31_8(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
259         veor      tmp0, tmp0, W;                \
260
261 #define WPRECALC_16_31_9(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
262         veor      W, tmp0, tmp1;                \
263
264 #define WPRECALC_16_31_10(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
265         vadd.u32  tmp0, W, curK;                \
266
267 #define WPRECALC_16_31_11(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
268         vst1.32   {tmp0}, [RWK];
269
270
271 /********* Precalc macros for rounds 32-79 ************************************/
272
273 #define WPRECALC_32_79_0(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
274         veor W, W_m28; \
275
276 #define WPRECALC_32_79_1(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
277         vext.8 tmp0, W_m08, W_m04, #8; \
278
279 #define WPRECALC_32_79_2(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
280         veor W, W_m16; \
281
282 #define WPRECALC_32_79_3(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
283         veor W, tmp0; \
284
285 #define WPRECALC_32_79_4(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
286         add RWK, sp, #(WK_offs(i&~3)); \
287
288 #define WPRECALC_32_79_5(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
289         vshl.u32 tmp1, W, #2; \
290
291 #define WPRECALC_32_79_6(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
292         vshr.u32 tmp0, W, #30; \
293
294 #define WPRECALC_32_79_7(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
295         vorr W, tmp0, tmp1; \
296
297 #define WPRECALC_32_79_8(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
298         vadd.u32 tmp0, W, curK; \
299
300 #define WPRECALC_32_79_9(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
301         vst1.32 {tmp0}, [RWK];
302
303
304 /* Other functional macros */
305
306 #define CLEAR_REG(reg) veor reg, reg;
307
308
309 /*
310  * Transform nblks*64 bytes (nblks*16 32-bit words) at DATA.
311  *
312  * unsigned int
313  * _gcry_sha1_transform_armv7_neon (void *ctx, const unsigned char *data,
314  *                                  size_t nblks)
315  */
316 .align 3
317 .globl _gcry_sha1_transform_armv7_neon
318 .type  _gcry_sha1_transform_armv7_neon,%function;
319 _gcry_sha1_transform_armv7_neon:
320   /* input:
321    *    r0: ctx, CTX
322    *    r1: data (64*nblks bytes)
323    *    r2: nblks
324    */
325
326   cmp RNBLKS, #0;
327   beq .Ldo_nothing;
328
329   push {r4-r12, lr};
330
331   GET_DATA_POINTER(RT3, .LK_VEC, _a);
332   vpush {q4-q7};
333
334   mov ROLDSTACK, sp;
335
336   /* Align stack. */
337   sub sp, #(16*4);
338   and sp, #(~(16-1));
339
340   vld1.32 {qK1-qK2}, [RT3]!; /* Load K1,K2 */
341
342   /* Get the values of the chaining variables. */
343   ldm RSTATE, {_a-_e};
344
345   vld1.32 {qK3-qK4}, [RT3]; /* Load K3,K4 */
346
347 #undef curK
348 #define curK qK1
349   /* Precalc 0-15. */
350   W_PRECALC_00_15();
351
352   b .Loop;
353
354 .ltorg
355 .Loop:
356   /* Transform 0-15 + Precalc 16-31. */
357   _R( _a, _b, _c, _d, _e, F1,  0, WPRECALC_16_31_0, WPRECALC_16_31_1, WPRECALC_16_31_2, 16, W4, W5, W6, W7, W0, _, _, _ );
358   _R( _e, _a, _b, _c, _d, F1,  1, WPRECALC_16_31_3, WPRECALC_16_31_4, WPRECALC_16_31_5, 16, W4, W5, W6, W7, W0, _, _, _ );
359   _R( _d, _e, _a, _b, _c, F1,  2, WPRECALC_16_31_6, WPRECALC_16_31_7, WPRECALC_16_31_8, 16, W4, W5, W6, W7, W0, _, _, _ );
360   _R( _c, _d, _e, _a, _b, F1,  3, WPRECALC_16_31_9, WPRECALC_16_31_10,WPRECALC_16_31_11,16, W4, W5, W6, W7, W0, _, _, _ );
361
362 #undef curK
363 #define curK qK2
364   _R( _b, _c, _d, _e, _a, F1,  4, WPRECALC_16_31_0, WPRECALC_16_31_1, WPRECALC_16_31_2, 20, W3, W4, W5, W6, W7, _, _, _ );
365   _R( _a, _b, _c, _d, _e, F1,  5, WPRECALC_16_31_3, WPRECALC_16_31_4, WPRECALC_16_31_5, 20, W3, W4, W5, W6, W7, _, _, _ );
366   _R( _e, _a, _b, _c, _d, F1,  6, WPRECALC_16_31_6, WPRECALC_16_31_7, WPRECALC_16_31_8, 20, W3, W4, W5, W6, W7, _, _, _ );
367   _R( _d, _e, _a, _b, _c, F1,  7, WPRECALC_16_31_9, WPRECALC_16_31_10,WPRECALC_16_31_11,20, W3, W4, W5, W6, W7, _, _, _ );
368
369   _R( _c, _d, _e, _a, _b, F1,  8, WPRECALC_16_31_0, WPRECALC_16_31_1, WPRECALC_16_31_2, 24, W2, W3, W4, W5, W6, _, _, _ );
370   _R( _b, _c, _d, _e, _a, F1,  9, WPRECALC_16_31_3, WPRECALC_16_31_4, WPRECALC_16_31_5, 24, W2, W3, W4, W5, W6, _, _, _ );
371   _R( _a, _b, _c, _d, _e, F1, 10, WPRECALC_16_31_6, WPRECALC_16_31_7, WPRECALC_16_31_8, 24, W2, W3, W4, W5, W6, _, _, _ );
372   _R( _e, _a, _b, _c, _d, F1, 11, WPRECALC_16_31_9, WPRECALC_16_31_10,WPRECALC_16_31_11,24, W2, W3, W4, W5, W6, _, _, _ );
373
374   _R( _d, _e, _a, _b, _c, F1, 12, WPRECALC_16_31_0, WPRECALC_16_31_1, WPRECALC_16_31_2, 28, W1, W2, W3, W4, W5, _, _, _ );
375   _R( _c, _d, _e, _a, _b, F1, 13, WPRECALC_16_31_3, WPRECALC_16_31_4, WPRECALC_16_31_5, 28, W1, W2, W3, W4, W5, _, _, _ );
376   _R( _b, _c, _d, _e, _a, F1, 14, WPRECALC_16_31_6, WPRECALC_16_31_7, WPRECALC_16_31_8, 28, W1, W2, W3, W4, W5, _, _, _ );
377   _R( _a, _b, _c, _d, _e, F1, 15, WPRECALC_16_31_9, WPRECALC_16_31_10,WPRECALC_16_31_11,28, W1, W2, W3, W4, W5, _, _, _ );
378
379   /* Transform 16-63 + Precalc 32-79. */
380   _R( _e, _a, _b, _c, _d, F1, 16, WPRECALC_32_79_0, WPRECALC_32_79_1, WPRECALC_32_79_2, 32, W0, W1, W2, W3, W4, W5, W6, W7);
381   _R( _d, _e, _a, _b, _c, F1, 17, WPRECALC_32_79_3, WPRECALC_32_79_4, WPRECALC_32_79_5, 32, W0, W1, W2, W3, W4, W5, W6, W7);
382   _R( _c, _d, _e, _a, _b, F1, 18, WPRECALC_32_79_6, dummy,            WPRECALC_32_79_7, 32, W0, W1, W2, W3, W4, W5, W6, W7);
383   _R( _b, _c, _d, _e, _a, F1, 19, WPRECALC_32_79_8, dummy,            WPRECALC_32_79_9, 32, W0, W1, W2, W3, W4, W5, W6, W7);
384
385   _R( _a, _b, _c, _d, _e, F2, 20, WPRECALC_32_79_0, WPRECALC_32_79_1, WPRECALC_32_79_2, 36, W7, W0, W1, W2, W3, W4, W5, W6);
386   _R( _e, _a, _b, _c, _d, F2, 21, WPRECALC_32_79_3, WPRECALC_32_79_4, WPRECALC_32_79_5, 36, W7, W0, W1, W2, W3, W4, W5, W6);
387   _R( _d, _e, _a, _b, _c, F2, 22, WPRECALC_32_79_6, dummy,            WPRECALC_32_79_7, 36, W7, W0, W1, W2, W3, W4, W5, W6);
388   _R( _c, _d, _e, _a, _b, F2, 23, WPRECALC_32_79_8, dummy,            WPRECALC_32_79_9, 36, W7, W0, W1, W2, W3, W4, W5, W6);
389
390 #undef curK
391 #define curK qK3
392   _R( _b, _c, _d, _e, _a, F2, 24, WPRECALC_32_79_0, WPRECALC_32_79_1, WPRECALC_32_79_2, 40, W6, W7, W0, W1, W2, W3, W4, W5);
393   _R( _a, _b, _c, _d, _e, F2, 25, WPRECALC_32_79_3, WPRECALC_32_79_4, WPRECALC_32_79_5, 40, W6, W7, W0, W1, W2, W3, W4, W5);
394   _R( _e, _a, _b, _c, _d, F2, 26, WPRECALC_32_79_6, dummy,            WPRECALC_32_79_7, 40, W6, W7, W0, W1, W2, W3, W4, W5);
395   _R( _d, _e, _a, _b, _c, F2, 27, WPRECALC_32_79_8, dummy,            WPRECALC_32_79_9, 40, W6, W7, W0, W1, W2, W3, W4, W5);
396
397   _R( _c, _d, _e, _a, _b, F2, 28, WPRECALC_32_79_0, WPRECALC_32_79_1, WPRECALC_32_79_2, 44, W5, W6, W7, W0, W1, W2, W3, W4);
398   _R( _b, _c, _d, _e, _a, F2, 29, WPRECALC_32_79_3, WPRECALC_32_79_4, WPRECALC_32_79_5, 44, W5, W6, W7, W0, W1, W2, W3, W4);
399   _R( _a, _b, _c, _d, _e, F2, 30, WPRECALC_32_79_6, dummy,            WPRECALC_32_79_7, 44, W5, W6, W7, W0, W1, W2, W3, W4);
400   _R( _e, _a, _b, _c, _d, F2, 31, WPRECALC_32_79_8, dummy,            WPRECALC_32_79_9, 44, W5, W6, W7, W0, W1, W2, W3, W4);
401
402   _R( _d, _e, _a, _b, _c, F2, 32, WPRECALC_32_79_0, WPRECALC_32_79_1, WPRECALC_32_79_2, 48, W4, W5, W6, W7, W0, W1, W2, W3);
403   _R( _c, _d, _e, _a, _b, F2, 33, WPRECALC_32_79_3, WPRECALC_32_79_4, WPRECALC_32_79_5, 48, W4, W5, W6, W7, W0, W1, W2, W3);
404   _R( _b, _c, _d, _e, _a, F2, 34, WPRECALC_32_79_6, dummy,            WPRECALC_32_79_7, 48, W4, W5, W6, W7, W0, W1, W2, W3);
405   _R( _a, _b, _c, _d, _e, F2, 35, WPRECALC_32_79_8, dummy,            WPRECALC_32_79_9, 48, W4, W5, W6, W7, W0, W1, W2, W3);
406
407   _R( _e, _a, _b, _c, _d, F2, 36, WPRECALC_32_79_0, WPRECALC_32_79_1, WPRECALC_32_79_2, 52, W3, W4, W5, W6, W7, W0, W1, W2);
408   _R( _d, _e, _a, _b, _c, F2, 37, WPRECALC_32_79_3, WPRECALC_32_79_4, WPRECALC_32_79_5, 52, W3, W4, W5, W6, W7, W0, W1, W2);
409   _R( _c, _d, _e, _a, _b, F2, 38, WPRECALC_32_79_6, dummy,            WPRECALC_32_79_7, 52, W3, W4, W5, W6, W7, W0, W1, W2);
410   _R( _b, _c, _d, _e, _a, F2, 39, WPRECALC_32_79_8, dummy,            WPRECALC_32_79_9, 52, W3, W4, W5, W6, W7, W0, W1, W2);
411
412   _R( _a, _b, _c, _d, _e, F3, 40, WPRECALC_32_79_0, WPRECALC_32_79_1, WPRECALC_32_79_2, 56, W2, W3, W4, W5, W6, W7, W0, W1);
413   _R( _e, _a, _b, _c, _d, F3, 41, WPRECALC_32_79_3, WPRECALC_32_79_4, WPRECALC_32_79_5, 56, W2, W3, W4, W5, W6, W7, W0, W1);
414   _R( _d, _e, _a, _b, _c, F3, 42, WPRECALC_32_79_6, dummy,            WPRECALC_32_79_7, 56, W2, W3, W4, W5, W6, W7, W0, W1);
415   _R( _c, _d, _e, _a, _b, F3, 43, WPRECALC_32_79_8, dummy,            WPRECALC_32_79_9, 56, W2, W3, W4, W5, W6, W7, W0, W1);
416
417 #undef curK
418 #define curK qK4
419   _R( _b, _c, _d, _e, _a, F3, 44, WPRECALC_32_79_0, WPRECALC_32_79_1, WPRECALC_32_79_2, 60, W1, W2, W3, W4, W5, W6, W7, W0);
420   _R( _a, _b, _c, _d, _e, F3, 45, WPRECALC_32_79_3, WPRECALC_32_79_4, WPRECALC_32_79_5, 60, W1, W2, W3, W4, W5, W6, W7, W0);
421   _R( _e, _a, _b, _c, _d, F3, 46, WPRECALC_32_79_6, dummy,            WPRECALC_32_79_7, 60, W1, W2, W3, W4, W5, W6, W7, W0);
422   _R( _d, _e, _a, _b, _c, F3, 47, WPRECALC_32_79_8, dummy,            WPRECALC_32_79_9, 60, W1, W2, W3, W4, W5, W6, W7, W0);
423
424   _R( _c, _d, _e, _a, _b, F3, 48, WPRECALC_32_79_0, WPRECALC_32_79_1, WPRECALC_32_79_2, 64, W0, W1, W2, W3, W4, W5, W6, W7);
425   _R( _b, _c, _d, _e, _a, F3, 49, WPRECALC_32_79_3, WPRECALC_32_79_4, WPRECALC_32_79_5, 64, W0, W1, W2, W3, W4, W5, W6, W7);
426   _R( _a, _b, _c, _d, _e, F3, 50, WPRECALC_32_79_6, dummy,            WPRECALC_32_79_7, 64, W0, W1, W2, W3, W4, W5, W6, W7);
427   _R( _e, _a, _b, _c, _d, F3, 51, WPRECALC_32_79_8, dummy,            WPRECALC_32_79_9, 64, W0, W1, W2, W3, W4, W5, W6, W7);
428
429   _R( _d, _e, _a, _b, _c, F3, 52, WPRECALC_32_79_0, WPRECALC_32_79_1, WPRECALC_32_79_2, 68, W7, W0, W1, W2, W3, W4, W5, W6);
430   _R( _c, _d, _e, _a, _b, F3, 53, WPRECALC_32_79_3, WPRECALC_32_79_4, WPRECALC_32_79_5, 68, W7, W0, W1, W2, W3, W4, W5, W6);
431   _R( _b, _c, _d, _e, _a, F3, 54, WPRECALC_32_79_6, dummy,            WPRECALC_32_79_7, 68, W7, W0, W1, W2, W3, W4, W5, W6);
432   _R( _a, _b, _c, _d, _e, F3, 55, WPRECALC_32_79_8, dummy,            WPRECALC_32_79_9, 68, W7, W0, W1, W2, W3, W4, W5, W6);
433
434   _R( _e, _a, _b, _c, _d, F3, 56, WPRECALC_32_79_0, WPRECALC_32_79_1, WPRECALC_32_79_2, 72, W6, W7, W0, W1, W2, W3, W4, W5);
435   _R( _d, _e, _a, _b, _c, F3, 57, WPRECALC_32_79_3, WPRECALC_32_79_4, WPRECALC_32_79_5, 72, W6, W7, W0, W1, W2, W3, W4, W5);
436   _R( _c, _d, _e, _a, _b, F3, 58, WPRECALC_32_79_6, dummy,            WPRECALC_32_79_7, 72, W6, W7, W0, W1, W2, W3, W4, W5);
437   _R( _b, _c, _d, _e, _a, F3, 59, WPRECALC_32_79_8, dummy,            WPRECALC_32_79_9, 72, W6, W7, W0, W1, W2, W3, W4, W5);
438
439   subs RNBLKS, #1;
440
441   _R( _a, _b, _c, _d, _e, F4, 60, WPRECALC_32_79_0, WPRECALC_32_79_1, WPRECALC_32_79_2, 76, W5, W6, W7, W0, W1, W2, W3, W4);
442   _R( _e, _a, _b, _c, _d, F4, 61, WPRECALC_32_79_3, WPRECALC_32_79_4, WPRECALC_32_79_5, 76, W5, W6, W7, W0, W1, W2, W3, W4);
443   _R( _d, _e, _a, _b, _c, F4, 62, WPRECALC_32_79_6, dummy,            WPRECALC_32_79_7, 76, W5, W6, W7, W0, W1, W2, W3, W4);
444   _R( _c, _d, _e, _a, _b, F4, 63, WPRECALC_32_79_8, dummy,            WPRECALC_32_79_9, 76, W5, W6, W7, W0, W1, W2, W3, W4);
445
446   beq .Lend;
447
448   /* Transform 64-79 + Precalc 0-15 of next block. */
449 #undef curK
450 #define curK qK1
451   _R( _b, _c, _d, _e, _a, F4, 64, WPRECALC_00_15_0, dummy, dummy, _, _, _, _, _, _, _, _, _ );
452   _R( _a, _b, _c, _d, _e, F4, 65, WPRECALC_00_15_1, dummy, dummy, _, _, _, _, _, _, _, _, _ );
453   _R( _e, _a, _b, _c, _d, F4, 66, WPRECALC_00_15_2, dummy, dummy, _, _, _, _, _, _, _, _, _ );
454   _R( _d, _e, _a, _b, _c, F4, 67, WPRECALC_00_15_3, dummy, dummy, _, _, _, _, _, _, _, _, _ );
455
456   _R( _c, _d, _e, _a, _b, F4, 68, dummy,            dummy, dummy, _, _, _, _, _, _, _, _, _ );
457   _R( _b, _c, _d, _e, _a, F4, 69, dummy,            dummy, dummy, _, _, _, _, _, _, _, _, _ );
458   _R( _a, _b, _c, _d, _e, F4, 70, WPRECALC_00_15_4, dummy, dummy, _, _, _, _, _, _, _, _, _ );
459   _R( _e, _a, _b, _c, _d, F4, 71, WPRECALC_00_15_5, dummy, dummy, _, _, _, _, _, _, _, _, _ );
460
461   _R( _d, _e, _a, _b, _c, F4, 72, dummy,            dummy, dummy, _, _, _, _, _, _, _, _, _ );
462   _R( _c, _d, _e, _a, _b, F4, 73, dummy,            dummy, dummy, _, _, _, _, _, _, _, _, _ );
463   _R( _b, _c, _d, _e, _a, F4, 74, WPRECALC_00_15_6, dummy, dummy, _, _, _, _, _, _, _, _, _ );
464   _R( _a, _b, _c, _d, _e, F4, 75, WPRECALC_00_15_7, dummy, dummy, _, _, _, _, _, _, _, _, _ );
465
466   _R( _e, _a, _b, _c, _d, F4, 76, WPRECALC_00_15_8, dummy, dummy, _, _, _, _, _, _, _, _, _ );
467   _R( _d, _e, _a, _b, _c, F4, 77, WPRECALC_00_15_9, dummy, dummy, _, _, _, _, _, _, _, _, _ );
468   _R( _c, _d, _e, _a, _b, F4, 78, WPRECALC_00_15_10, dummy, dummy, _, _, _, _, _, _, _, _, _ );
469   _R( _b, _c, _d, _e, _a, F4, 79, WPRECALC_00_15_11, dummy, WPRECALC_00_15_12, _, _, _, _, _, _, _, _, _ );
470
471   /* Update the chaining variables. */
472   ldm RSTATE, {RT0-RT3};
473   add _a, RT0;
474   ldr RT0, [RSTATE, #state_h4];
475   add _b, RT1;
476   add _c, RT2;
477   add _d, RT3;
478   add _e, RT0;
479   stm RSTATE, {_a-_e};
480
481   b .Loop;
482
483 .ltorg
484 .Lend:
485   /* Transform 64-79 + Clear XMM registers. */
486   R( _b, _c, _d, _e, _a, F4, 64 );
487   R( _a, _b, _c, _d, _e, F4, 65 ); CLEAR_REG(tmp0);
488   R( _e, _a, _b, _c, _d, F4, 66 ); CLEAR_REG(tmp1);
489   R( _d, _e, _a, _b, _c, F4, 67 ); CLEAR_REG(W0);
490   R( _c, _d, _e, _a, _b, F4, 68 ); CLEAR_REG(W1);
491   R( _b, _c, _d, _e, _a, F4, 69 ); CLEAR_REG(W2);
492   R( _a, _b, _c, _d, _e, F4, 70 ); CLEAR_REG(W3);
493   R( _e, _a, _b, _c, _d, F4, 71 ); CLEAR_REG(W4);
494   R( _d, _e, _a, _b, _c, F4, 72 ); CLEAR_REG(W5);
495   R( _c, _d, _e, _a, _b, F4, 73 ); CLEAR_REG(W6);
496   R( _b, _c, _d, _e, _a, F4, 74 ); CLEAR_REG(W7);
497   R( _a, _b, _c, _d, _e, F4, 75 );
498   R( _e, _a, _b, _c, _d, F4, 76 );
499   R( _d, _e, _a, _b, _c, F4, 77 );
500   R( _c, _d, _e, _a, _b, F4, 78 );
501   R( _b, _c, _d, _e, _a, F4, 79 );
502
503   mov sp, ROLDSTACK;
504
505   /* Update the chaining variables. */
506   ldm RSTATE, {RT0-RT3};
507   add _a, RT0;
508   ldr RT0, [RSTATE, #state_h4];
509   add _b, RT1;
510   add _c, RT2;
511   add _d, RT3;
512   vpop {q4-q7};
513   add _e, RT0;
514   stm RSTATE, {_a-_e};
515
516   /* burn_stack */
517   mov r0, #(16*4 + 16*4 + 15);
518
519   pop {r4-r12, pc};
520
521 .Ldo_nothing:
522   mov r0, #0;
523   bx lr
524 .size _gcry_sha1_transform_armv7_neon,.-_gcry_sha1_transform_armv7_neon;
525
526 #endif