Add carryless 8-bit addition fast-path for AES-NI CTR mode
[libgcrypt.git] / cipher / sha1-ssse3-amd64.S
1 /* sha1-ssse3-amd64.S - Intel SSSE3 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 /*
24  * Intel SSSE3 accelerated SHA-1 implementation based on white paper:
25  *  "Improving the Performance of the Secure Hash Algorithm (SHA-1)"
26  *  http://software.intel.com/en-us/articles/improving-the-performance-of-the-secure-hash-algorithm-1
27  */
28
29 #ifdef __x86_64__
30 #include <config.h>
31
32 #if (defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \
33      defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS)) && \
34     defined(HAVE_GCC_INLINE_ASM_SSSE3) && defined(USE_SHA1)
35
36 #ifdef __PIC__
37 #  define RIP (%rip)
38 #else
39 #  define RIP
40 #endif
41
42
43 #ifdef HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS
44 # define ELF(...) __VA_ARGS__
45 #else
46 # define ELF(...) /*_*/
47 #endif
48
49
50 /* Context structure */
51
52 #define state_h0 0
53 #define state_h1 4
54 #define state_h2 8
55 #define state_h3 12
56 #define state_h4 16
57
58
59 /* Constants */
60
61 .data
62 #define K1  0x5A827999
63 #define K2  0x6ED9EBA1
64 #define K3  0x8F1BBCDC
65 #define K4  0xCA62C1D6
66 .align 16
67 .LK_XMM:
68 .LK1:   .long K1, K1, K1, K1
69 .LK2:   .long K2, K2, K2, K2
70 .LK3:   .long K3, K3, K3, K3
71 .LK4:   .long K4, K4, K4, K4
72
73 .Lbswap_shufb_ctl:
74         .long 0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f
75
76
77 /* Register macros */
78
79 #define RSTATE %r8
80 #define RDATA %r9
81 #define ROLDSTACK %r10
82 #define RNBLKS %r11
83
84 #define a %eax
85 #define b %ebx
86 #define c %ecx
87 #define d %edx
88 #define e %edi
89
90 #define RT0 %esi
91 #define RT1 %ebp
92
93 #define Wtmp0 %xmm0
94 #define Wtmp1 %xmm1
95
96 #define W0 %xmm2
97 #define W1 %xmm3
98 #define W2 %xmm4
99 #define W3 %xmm5
100 #define W4 %xmm6
101 #define W5 %xmm7
102 #define W6 %xmm8
103 #define W7 %xmm9
104
105 #define BSWAP_REG %xmm10
106
107
108 /* Round function macros. */
109
110 #define WK(i) (((i) & 15) * 4)(%rsp)
111
112 #define R_F1(a,b,c,d,e,i) \
113         movl c, RT0; \
114         addl WK(i), e; \
115         xorl d, RT0; \
116         movl a, RT1; \
117         andl b, RT0; \
118         roll $30, b; \
119         xorl d, RT0; \
120         leal (RT0,e), e; \
121         roll $5, RT1; \
122         addl RT1, e;
123
124 #define R_F2(a,b,c,d,e,i) \
125         movl c, RT0; \
126         addl WK(i), e; \
127         xorl b, RT0; \
128         roll $30, b; \
129         xorl d, RT0; \
130         movl a, RT1; \
131         leal (RT0,e), e; \
132         roll $5, RT1; \
133         addl RT1, e;
134
135 #define R_F3(a,b,c,d,e,i) \
136         movl c, RT0; \
137         movl b, RT1; \
138         xorl b, RT0; \
139         andl c, RT1; \
140         andl d, RT0; \
141         addl RT1, e; \
142         addl WK(i), e; \
143         roll $30, b; \
144         movl a, RT1; \
145         leal (RT0,e), e; \
146         roll $5, RT1; \
147         addl RT1, e;
148
149 #define R_F4(a,b,c,d,e,i) R_F2(a,b,c,d,e,i)
150
151 #define R(a,b,c,d,e,f,i) \
152         R_##f(a,b,c,d,e,i)
153
154
155 /* Input expansion macros. */
156
157 #define W_PRECALC_00_15_0(i, W, tmp0) \
158         movdqu (4*(i))(RDATA), tmp0;
159
160 #define W_PRECALC_00_15_1(i, W, tmp0) \
161         pshufb BSWAP_REG, tmp0; \
162         movdqa tmp0, W;
163
164 #define W_PRECALC_00_15_2(i, W, tmp0) \
165         paddd (.LK_XMM + ((i)/20)*16) RIP, tmp0;
166
167 #define W_PRECALC_00_15_3(i, W, tmp0) \
168         movdqa tmp0, WK(i&~3);
169
170 #define W_PRECALC_16_31_0(i, W, W_m04, W_m08, W_m12, W_m16, tmp0, tmp1) \
171         movdqa W_m12, W; \
172         palignr $8, W_m16, W; \
173         movdqa W_m04, tmp0; \
174         psrldq $4, tmp0; \
175         pxor W_m08, W;
176
177 #define W_PRECALC_16_31_1(i, W, W_m04, W_m08, W_m12, W_m16, tmp0, tmp1) \
178         pxor W_m16, tmp0; \
179         pxor tmp0, W; \
180         movdqa W, tmp1; \
181         movdqa W, tmp0; \
182         pslldq $12, tmp1;
183
184 #define W_PRECALC_16_31_2(i, W, W_m04, W_m08, W_m12, W_m16, tmp0, tmp1) \
185         psrld $31, W; \
186         pslld $1, tmp0; \
187         por W, tmp0; \
188         movdqa tmp1, W; \
189         psrld $30, tmp1; \
190         pslld $2, W;
191
192 #define W_PRECALC_16_31_3(i, W, W_m04, W_m08, W_m12, W_m16, tmp0, tmp1) \
193         pxor W, tmp0; \
194         pxor tmp1, tmp0; \
195         movdqa tmp0, W; \
196         paddd (.LK_XMM + ((i)/20)*16) RIP, tmp0; \
197         movdqa tmp0, WK((i)&~3);
198
199 #define W_PRECALC_32_79_0(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28, tmp0) \
200         movdqa W_m04, tmp0; \
201         pxor W_m28, W; \
202         palignr $8, W_m08, tmp0;
203
204 #define W_PRECALC_32_79_1(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28, tmp0) \
205         pxor W_m16, W; \
206         pxor tmp0, W; \
207         movdqa W, tmp0;
208
209 #define W_PRECALC_32_79_2(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28, tmp0) \
210         psrld $30, W; \
211         pslld $2, tmp0; \
212         por W, tmp0;
213
214 #define W_PRECALC_32_79_3(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28, tmp0) \
215         movdqa tmp0, W; \
216         paddd (.LK_XMM + ((i)/20)*16) RIP, tmp0; \
217         movdqa tmp0, WK((i)&~3);
218
219 #define CLEAR_REG(reg) pxor reg, reg;
220
221
222 /*
223  * Transform nblks*64 bytes (nblks*16 32-bit words) at DATA.
224  *
225  * unsigned int
226  * _gcry_sha1_transform_amd64_ssse3 (void *ctx, const unsigned char *data,
227  *                                   size_t nblks)
228  */
229 .text
230 .globl _gcry_sha1_transform_amd64_ssse3
231 ELF(.type _gcry_sha1_transform_amd64_ssse3,@function)
232 .align 16
233 _gcry_sha1_transform_amd64_ssse3:
234   /* input:
235    *    %rdi: ctx, CTX
236    *    %rsi: data (64*nblks bytes)
237    *    %rdx: nblks
238    */
239
240   xorl %eax, %eax;
241   cmpq $0, %rdx;
242   jz .Lret;
243
244   movq %rdx, RNBLKS;
245   movq %rdi, RSTATE;
246   movq %rsi, RDATA;
247   pushq %rbx;
248   pushq %rbp;
249
250   movq %rsp, ROLDSTACK;
251
252   subq $(16*4), %rsp;
253   andq $(~31), %rsp;
254
255   /* Get the values of the chaining variables. */
256   movl state_h0(RSTATE), a;
257   movl state_h1(RSTATE), b;
258   movl state_h2(RSTATE), c;
259   movl state_h3(RSTATE), d;
260   movl state_h4(RSTATE), e;
261
262   movdqa .Lbswap_shufb_ctl RIP, BSWAP_REG;
263
264   /* Precalc 0-15. */
265   W_PRECALC_00_15_0(0, W0, Wtmp0);
266   W_PRECALC_00_15_1(1, W0, Wtmp0);
267   W_PRECALC_00_15_2(2, W0, Wtmp0);
268   W_PRECALC_00_15_3(3, W0, Wtmp0);
269   W_PRECALC_00_15_0(4, W7, Wtmp0);
270   W_PRECALC_00_15_1(5, W7, Wtmp0);
271   W_PRECALC_00_15_2(6, W7, Wtmp0);
272   W_PRECALC_00_15_3(7, W7, Wtmp0);
273   W_PRECALC_00_15_0(8, W6, Wtmp0);
274   W_PRECALC_00_15_1(9, W6, Wtmp0);
275   W_PRECALC_00_15_2(10, W6, Wtmp0);
276   W_PRECALC_00_15_3(11, W6, Wtmp0);
277   W_PRECALC_00_15_0(12, W5, Wtmp0);
278   W_PRECALC_00_15_1(13, W5, Wtmp0);
279   W_PRECALC_00_15_2(14, W5, Wtmp0);
280   W_PRECALC_00_15_3(15, W5, Wtmp0);
281
282 .align 8
283 .Loop:
284   addq $64, RDATA;
285
286   /* Transform 0-15 + Precalc 16-31. */
287   R( a, b, c, d, e, F1,  0 ); W_PRECALC_16_31_0(16, W4, W5, W6, W7, W0, Wtmp0, Wtmp1);
288   R( e, a, b, c, d, F1,  1 ); W_PRECALC_16_31_1(17, W4, W5, W6, W7, W0, Wtmp0, Wtmp1);
289   R( d, e, a, b, c, F1,  2 ); W_PRECALC_16_31_2(18, W4, W5, W6, W7, W0, Wtmp0, Wtmp1);
290   R( c, d, e, a, b, F1,  3 ); W_PRECALC_16_31_3(19, W4, W5, W6, W7, W0, Wtmp0, Wtmp1);
291   R( b, c, d, e, a, F1,  4 ); W_PRECALC_16_31_0(20, W3, W4, W5, W6, W7, Wtmp0, Wtmp1);
292   R( a, b, c, d, e, F1,  5 ); W_PRECALC_16_31_1(21, W3, W4, W5, W6, W7, Wtmp0, Wtmp1);
293   R( e, a, b, c, d, F1,  6 ); W_PRECALC_16_31_2(22, W3, W4, W5, W6, W7, Wtmp0, Wtmp1);
294   R( d, e, a, b, c, F1,  7 ); W_PRECALC_16_31_3(23, W3, W4, W5, W6, W7, Wtmp0, Wtmp1);
295   R( c, d, e, a, b, F1,  8 ); W_PRECALC_16_31_0(24, W2, W3, W4, W5, W6, Wtmp0, Wtmp1);
296   R( b, c, d, e, a, F1,  9 ); W_PRECALC_16_31_1(25, W2, W3, W4, W5, W6, Wtmp0, Wtmp1);
297   R( a, b, c, d, e, F1, 10 ); W_PRECALC_16_31_2(26, W2, W3, W4, W5, W6, Wtmp0, Wtmp1);
298   R( e, a, b, c, d, F1, 11 ); W_PRECALC_16_31_3(27, W2, W3, W4, W5, W6, Wtmp0, Wtmp1);
299   R( d, e, a, b, c, F1, 12 ); W_PRECALC_16_31_0(28, W1, W2, W3, W4, W5, Wtmp0, Wtmp1);
300   R( c, d, e, a, b, F1, 13 ); W_PRECALC_16_31_1(29, W1, W2, W3, W4, W5, Wtmp0, Wtmp1);
301   R( b, c, d, e, a, F1, 14 ); W_PRECALC_16_31_2(30, W1, W2, W3, W4, W5, Wtmp0, Wtmp1);
302   R( a, b, c, d, e, F1, 15 ); W_PRECALC_16_31_3(31, W1, W2, W3, W4, W5, Wtmp0, Wtmp1);
303
304   /* Transform 16-63 + Precalc 32-79. */
305   R( e, a, b, c, d, F1, 16 ); W_PRECALC_32_79_0(32, W0, W1, W2, W3, W4, W5, W6, W7, Wtmp0);
306   R( d, e, a, b, c, F1, 17 ); W_PRECALC_32_79_1(33, W0, W1, W2, W3, W4, W5, W6, W7, Wtmp0);
307   R( c, d, e, a, b, F1, 18 ); W_PRECALC_32_79_2(34, W0, W1, W2, W3, W4, W5, W6, W7, Wtmp0);
308   R( b, c, d, e, a, F1, 19 ); W_PRECALC_32_79_3(35, W0, W1, W2, W3, W4, W5, W6, W7, Wtmp0);
309   R( a, b, c, d, e, F2, 20 ); W_PRECALC_32_79_0(36, W7, W0, W1, W2, W3, W4, W5, W6, Wtmp0);
310   R( e, a, b, c, d, F2, 21 ); W_PRECALC_32_79_1(37, W7, W0, W1, W2, W3, W4, W5, W6, Wtmp0);
311   R( d, e, a, b, c, F2, 22 ); W_PRECALC_32_79_2(38, W7, W0, W1, W2, W3, W4, W5, W6, Wtmp0);
312   R( c, d, e, a, b, F2, 23 ); W_PRECALC_32_79_3(39, W7, W0, W1, W2, W3, W4, W5, W6, Wtmp0);
313   R( b, c, d, e, a, F2, 24 ); W_PRECALC_32_79_0(40, W6, W7, W0, W1, W2, W3, W4, W5, Wtmp0);
314   R( a, b, c, d, e, F2, 25 ); W_PRECALC_32_79_1(41, W6, W7, W0, W1, W2, W3, W4, W5, Wtmp0);
315   R( e, a, b, c, d, F2, 26 ); W_PRECALC_32_79_2(42, W6, W7, W0, W1, W2, W3, W4, W5, Wtmp0);
316   R( d, e, a, b, c, F2, 27 ); W_PRECALC_32_79_3(43, W6, W7, W0, W1, W2, W3, W4, W5, Wtmp0);
317   R( c, d, e, a, b, F2, 28 ); W_PRECALC_32_79_0(44, W5, W6, W7, W0, W1, W2, W3, W4, Wtmp0);
318   R( b, c, d, e, a, F2, 29 ); W_PRECALC_32_79_1(45, W5, W6, W7, W0, W1, W2, W3, W4, Wtmp0);
319   R( a, b, c, d, e, F2, 30 ); W_PRECALC_32_79_2(46, W5, W6, W7, W0, W1, W2, W3, W4, Wtmp0);
320   R( e, a, b, c, d, F2, 31 ); W_PRECALC_32_79_3(47, W5, W6, W7, W0, W1, W2, W3, W4, Wtmp0);
321   R( d, e, a, b, c, F2, 32 ); W_PRECALC_32_79_0(48, W4, W5, W6, W7, W0, W1, W2, W3, Wtmp0);
322   R( c, d, e, a, b, F2, 33 ); W_PRECALC_32_79_1(49, W4, W5, W6, W7, W0, W1, W2, W3, Wtmp0);
323   R( b, c, d, e, a, F2, 34 ); W_PRECALC_32_79_2(50, W4, W5, W6, W7, W0, W1, W2, W3, Wtmp0);
324   R( a, b, c, d, e, F2, 35 ); W_PRECALC_32_79_3(51, W4, W5, W6, W7, W0, W1, W2, W3, Wtmp0);
325   R( e, a, b, c, d, F2, 36 ); W_PRECALC_32_79_0(52, W3, W4, W5, W6, W7, W0, W1, W2, Wtmp0);
326   R( d, e, a, b, c, F2, 37 ); W_PRECALC_32_79_1(53, W3, W4, W5, W6, W7, W0, W1, W2, Wtmp0);
327   R( c, d, e, a, b, F2, 38 ); W_PRECALC_32_79_2(54, W3, W4, W5, W6, W7, W0, W1, W2, Wtmp0);
328   R( b, c, d, e, a, F2, 39 ); W_PRECALC_32_79_3(55, W3, W4, W5, W6, W7, W0, W1, W2, Wtmp0);
329   R( a, b, c, d, e, F3, 40 ); W_PRECALC_32_79_0(56, W2, W3, W4, W5, W6, W7, W0, W1, Wtmp0);
330   R( e, a, b, c, d, F3, 41 ); W_PRECALC_32_79_1(57, W2, W3, W4, W5, W6, W7, W0, W1, Wtmp0);
331   R( d, e, a, b, c, F3, 42 ); W_PRECALC_32_79_2(58, W2, W3, W4, W5, W6, W7, W0, W1, Wtmp0);
332   R( c, d, e, a, b, F3, 43 ); W_PRECALC_32_79_3(59, W2, W3, W4, W5, W6, W7, W0, W1, Wtmp0);
333   R( b, c, d, e, a, F3, 44 ); W_PRECALC_32_79_0(60, W1, W2, W3, W4, W5, W6, W7, W0, Wtmp0);
334   R( a, b, c, d, e, F3, 45 ); W_PRECALC_32_79_1(61, W1, W2, W3, W4, W5, W6, W7, W0, Wtmp0);
335   R( e, a, b, c, d, F3, 46 ); W_PRECALC_32_79_2(62, W1, W2, W3, W4, W5, W6, W7, W0, Wtmp0);
336   R( d, e, a, b, c, F3, 47 ); W_PRECALC_32_79_3(63, W1, W2, W3, W4, W5, W6, W7, W0, Wtmp0);
337   R( c, d, e, a, b, F3, 48 ); W_PRECALC_32_79_0(64, W0, W1, W2, W3, W4, W5, W6, W7, Wtmp0);
338   R( b, c, d, e, a, F3, 49 ); W_PRECALC_32_79_1(65, W0, W1, W2, W3, W4, W5, W6, W7, Wtmp0);
339   R( a, b, c, d, e, F3, 50 ); W_PRECALC_32_79_2(66, W0, W1, W2, W3, W4, W5, W6, W7, Wtmp0);
340   R( e, a, b, c, d, F3, 51 ); W_PRECALC_32_79_3(67, W0, W1, W2, W3, W4, W5, W6, W7, Wtmp0);
341   R( d, e, a, b, c, F3, 52 ); W_PRECALC_32_79_0(68, W7, W0, W1, W2, W3, W4, W5, W6, Wtmp0);
342   R( c, d, e, a, b, F3, 53 ); W_PRECALC_32_79_1(69, W7, W0, W1, W2, W3, W4, W5, W6, Wtmp0);
343   R( b, c, d, e, a, F3, 54 ); W_PRECALC_32_79_2(70, W7, W0, W1, W2, W3, W4, W5, W6, Wtmp0);
344   R( a, b, c, d, e, F3, 55 ); W_PRECALC_32_79_3(71, W7, W0, W1, W2, W3, W4, W5, W6, Wtmp0);
345   R( e, a, b, c, d, F3, 56 ); W_PRECALC_32_79_0(72, W6, W7, W0, W1, W2, W3, W4, W5, Wtmp0);
346   R( d, e, a, b, c, F3, 57 ); W_PRECALC_32_79_1(73, W6, W7, W0, W1, W2, W3, W4, W5, Wtmp0);
347   R( c, d, e, a, b, F3, 58 ); W_PRECALC_32_79_2(74, W6, W7, W0, W1, W2, W3, W4, W5, Wtmp0);
348   R( b, c, d, e, a, F3, 59 ); W_PRECALC_32_79_3(75, W6, W7, W0, W1, W2, W3, W4, W5, Wtmp0);
349   R( a, b, c, d, e, F4, 60 ); W_PRECALC_32_79_0(76, W5, W6, W7, W0, W1, W2, W3, W4, Wtmp0);
350   R( e, a, b, c, d, F4, 61 ); W_PRECALC_32_79_1(77, W5, W6, W7, W0, W1, W2, W3, W4, Wtmp0);
351   R( d, e, a, b, c, F4, 62 ); W_PRECALC_32_79_2(78, W5, W6, W7, W0, W1, W2, W3, W4, Wtmp0);
352   R( c, d, e, a, b, F4, 63 ); W_PRECALC_32_79_3(79, W5, W6, W7, W0, W1, W2, W3, W4, Wtmp0);
353
354   decq RNBLKS;
355   jz .Lend;
356
357   /* Transform 64-79 + Precalc 0-15 of next block. */
358   R( b, c, d, e, a, F4, 64 ); W_PRECALC_00_15_0(0, W0, Wtmp0);
359   R( a, b, c, d, e, F4, 65 ); W_PRECALC_00_15_1(1, W0, Wtmp0);
360   R( e, a, b, c, d, F4, 66 ); W_PRECALC_00_15_2(2, W0, Wtmp0);
361   R( d, e, a, b, c, F4, 67 ); W_PRECALC_00_15_3(3, W0, Wtmp0);
362   R( c, d, e, a, b, F4, 68 ); W_PRECALC_00_15_0(4, W7, Wtmp0);
363   R( b, c, d, e, a, F4, 69 ); W_PRECALC_00_15_1(5, W7, Wtmp0);
364   R( a, b, c, d, e, F4, 70 ); W_PRECALC_00_15_2(6, W7, Wtmp0);
365   R( e, a, b, c, d, F4, 71 ); W_PRECALC_00_15_3(7, W7, Wtmp0);
366   R( d, e, a, b, c, F4, 72 ); W_PRECALC_00_15_0(8, W6, Wtmp0);
367   R( c, d, e, a, b, F4, 73 ); W_PRECALC_00_15_1(9, W6, Wtmp0);
368   R( b, c, d, e, a, F4, 74 ); W_PRECALC_00_15_2(10, W6, Wtmp0);
369   R( a, b, c, d, e, F4, 75 ); W_PRECALC_00_15_3(11, W6, Wtmp0);
370   R( e, a, b, c, d, F4, 76 ); W_PRECALC_00_15_0(12, W5, Wtmp0);
371   R( d, e, a, b, c, F4, 77 ); W_PRECALC_00_15_1(13, W5, Wtmp0);
372   R( c, d, e, a, b, F4, 78 );
373   addl state_h0(RSTATE), a;   W_PRECALC_00_15_2(14, W5, Wtmp0);
374   R( b, c, d, e, a, F4, 79 ); W_PRECALC_00_15_3(15, W5, Wtmp0);
375
376   /* Update the chaining variables. */
377   addl state_h3(RSTATE), d;
378   addl state_h2(RSTATE), c;
379   addl state_h1(RSTATE), b;
380   addl state_h4(RSTATE), e;
381
382   movl d, state_h3(RSTATE);
383   movl c, state_h2(RSTATE);
384   movl b, state_h1(RSTATE);
385   movl a, state_h0(RSTATE);
386   movl e, state_h4(RSTATE);
387
388   jmp .Loop;
389
390 .align 16
391 .Lend:
392   /* Transform 64-79 + Clear XMM registers. */
393   R( b, c, d, e, a, F4, 64 ); CLEAR_REG(BSWAP_REG);
394   R( a, b, c, d, e, F4, 65 ); CLEAR_REG(Wtmp0);
395   R( e, a, b, c, d, F4, 66 ); CLEAR_REG(Wtmp1);
396   R( d, e, a, b, c, F4, 67 ); CLEAR_REG(W0);
397   R( c, d, e, a, b, F4, 68 ); CLEAR_REG(W1);
398   R( b, c, d, e, a, F4, 69 ); CLEAR_REG(W2);
399   R( a, b, c, d, e, F4, 70 ); CLEAR_REG(W3);
400   R( e, a, b, c, d, F4, 71 ); CLEAR_REG(W4);
401   R( d, e, a, b, c, F4, 72 ); CLEAR_REG(W5);
402   R( c, d, e, a, b, F4, 73 ); CLEAR_REG(W6);
403   R( b, c, d, e, a, F4, 74 ); CLEAR_REG(W7);
404   R( a, b, c, d, e, F4, 75 );
405   R( e, a, b, c, d, F4, 76 );
406   R( d, e, a, b, c, F4, 77 );
407   R( c, d, e, a, b, F4, 78 );
408   addl state_h0(RSTATE), a;
409   R( b, c, d, e, a, F4, 79 );
410
411   /* Update the chaining variables. */
412   addl state_h3(RSTATE), d;
413   addl state_h2(RSTATE), c;
414   addl state_h1(RSTATE), b;
415   addl state_h4(RSTATE), e;
416
417   movl d, state_h3(RSTATE);
418   movl c, state_h2(RSTATE);
419   movl b, state_h1(RSTATE);
420   movl a, state_h0(RSTATE);
421   movl e, state_h4(RSTATE);
422
423   movq ROLDSTACK, %rsp;
424
425   popq %rbp;
426   popq %rbx;
427
428   /* burn_stack */
429   movl $(16*4 + 2*8 + 31), %eax;
430
431 .Lret:
432   ret;
433
434 #endif
435 #endif