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