added a subset of Crypto++ 5.6.0 with 48% faster ASM SHA-256, combined speedup 2...
[novacoin.git] / cryptopp / sha.cpp
1 // sha.cpp - modified by Wei Dai from Steve Reid's public domain sha1.c\r
2 \r
3 // Steve Reid implemented SHA-1. Wei Dai implemented SHA-2.\r
4 // Both are in the public domain.\r
5 \r
6 // use "cl /EP /P /DCRYPTOPP_GENERATE_X64_MASM sha.cpp" to generate MASM code\r
7 \r
8 #include "pch.h"\r
9 \r
10 #ifndef CRYPTOPP_IMPORTS\r
11 #ifndef CRYPTOPP_GENERATE_X64_MASM\r
12 \r
13 #include "sha.h"\r
14 #include "misc.h"\r
15 #include "cpu.h"\r
16 \r
17 NAMESPACE_BEGIN(CryptoPP)\r
18 \r
19 // start of Steve Reid's code\r
20 \r
21 #define blk0(i) (W[i] = data[i])\r
22 #define blk1(i) (W[i&15] = rotlFixed(W[(i+13)&15]^W[(i+8)&15]^W[(i+2)&15]^W[i&15],1))\r
23 \r
24 void SHA1::InitState(HashWordType *state)\r
25 {\r
26         state[0] = 0x67452301L;\r
27         state[1] = 0xEFCDAB89L;\r
28         state[2] = 0x98BADCFEL;\r
29         state[3] = 0x10325476L;\r
30         state[4] = 0xC3D2E1F0L;\r
31 }\r
32 \r
33 #define f1(x,y,z) (z^(x&(y^z)))\r
34 #define f2(x,y,z) (x^y^z)\r
35 #define f3(x,y,z) ((x&y)|(z&(x|y)))\r
36 #define f4(x,y,z) (x^y^z)\r
37 \r
38 /* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */\r
39 #define R0(v,w,x,y,z,i) z+=f1(w,x,y)+blk0(i)+0x5A827999+rotlFixed(v,5);w=rotlFixed(w,30);\r
40 #define R1(v,w,x,y,z,i) z+=f1(w,x,y)+blk1(i)+0x5A827999+rotlFixed(v,5);w=rotlFixed(w,30);\r
41 #define R2(v,w,x,y,z,i) z+=f2(w,x,y)+blk1(i)+0x6ED9EBA1+rotlFixed(v,5);w=rotlFixed(w,30);\r
42 #define R3(v,w,x,y,z,i) z+=f3(w,x,y)+blk1(i)+0x8F1BBCDC+rotlFixed(v,5);w=rotlFixed(w,30);\r
43 #define R4(v,w,x,y,z,i) z+=f4(w,x,y)+blk1(i)+0xCA62C1D6+rotlFixed(v,5);w=rotlFixed(w,30);\r
44 \r
45 void SHA1::Transform(word32 *state, const word32 *data)\r
46 {\r
47         word32 W[16];\r
48     /* Copy context->state[] to working vars */\r
49     word32 a = state[0];\r
50     word32 b = state[1];\r
51     word32 c = state[2];\r
52     word32 d = state[3];\r
53     word32 e = state[4];\r
54     /* 4 rounds of 20 operations each. Loop unrolled. */\r
55     R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);\r
56     R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);\r
57     R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);\r
58     R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);\r
59     R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);\r
60     R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);\r
61     R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);\r
62     R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);\r
63     R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);\r
64     R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);\r
65     R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);\r
66     R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);\r
67     R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);\r
68     R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);\r
69     R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);\r
70     R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);\r
71     R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);\r
72     R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);\r
73     R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);\r
74     R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);\r
75     /* Add the working vars back into context.state[] */\r
76     state[0] += a;\r
77     state[1] += b;\r
78     state[2] += c;\r
79     state[3] += d;\r
80     state[4] += e;\r
81 }\r
82 \r
83 // end of Steve Reid's code\r
84 \r
85 // *************************************************************\r
86 \r
87 void SHA224::InitState(HashWordType *state)\r
88 {\r
89         static const word32 s[8] = {0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939, 0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4};\r
90         memcpy(state, s, sizeof(s));\r
91 }\r
92 \r
93 void SHA256::InitState(HashWordType *state)\r
94 {\r
95         static const word32 s[8] = {0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19};\r
96         memcpy(state, s, sizeof(s));\r
97 }\r
98 \r
99 #if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE\r
100 CRYPTOPP_ALIGN_DATA(16) extern const word32 SHA256_K[64] CRYPTOPP_SECTION_ALIGN16 = {\r
101 #else\r
102 extern const word32 SHA256_K[64] = {\r
103 #endif\r
104         0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,\r
105         0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,\r
106         0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,\r
107         0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,\r
108         0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,\r
109         0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,\r
110         0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,\r
111         0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,\r
112         0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,\r
113         0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,\r
114         0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,\r
115         0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,\r
116         0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,\r
117         0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,\r
118         0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,\r
119         0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2\r
120 };\r
121 \r
122 #endif // #ifndef CRYPTOPP_GENERATE_X64_MASM\r
123 \r
124 #if defined(CRYPTOPP_X86_ASM_AVAILABLE) || defined(CRYPTOPP_GENERATE_X64_MASM)\r
125 \r
126 #pragma warning(disable: 4731)  // frame pointer register 'ebp' modified by inline assembly code\r
127 \r
128 static void CRYPTOPP_FASTCALL X86_SHA256_HashBlocks(word32 *state, const word32 *data, size_t len\r
129 #if defined(_MSC_VER) && (_MSC_VER == 1200)\r
130         , ...   // VC60 workaround: prevent VC 6 from inlining this function\r
131 #endif\r
132         )\r
133 {\r
134 #if defined(_MSC_VER) && (_MSC_VER == 1200)\r
135         AS2(mov ecx, [state])\r
136         AS2(mov edx, [data])\r
137 #endif\r
138 \r
139         #define LOCALS_SIZE     8*4 + 16*4 + 4*WORD_SZ\r
140         #define H(i)            [BASE+ASM_MOD(1024+7-(i),8)*4]\r
141         #define G(i)            H(i+1)\r
142         #define F(i)            H(i+2)\r
143         #define E(i)            H(i+3)\r
144         #define D(i)            H(i+4)\r
145         #define C(i)            H(i+5)\r
146         #define B(i)            H(i+6)\r
147         #define A(i)            H(i+7)\r
148         #define Wt(i)           BASE+8*4+ASM_MOD(1024+15-(i),16)*4\r
149         #define Wt_2(i)         Wt((i)-2)\r
150         #define Wt_15(i)        Wt((i)-15)\r
151         #define Wt_7(i)         Wt((i)-7)\r
152         #define K_END           [BASE+8*4+16*4+0*WORD_SZ]\r
153         #define STATE_SAVE      [BASE+8*4+16*4+1*WORD_SZ]\r
154         #define DATA_SAVE       [BASE+8*4+16*4+2*WORD_SZ]\r
155         #define DATA_END        [BASE+8*4+16*4+3*WORD_SZ]\r
156         #define Kt(i)           WORD_REG(si)+(i)*4\r
157 #if CRYPTOPP_BOOL_X86\r
158         #define BASE            esp+4\r
159 #elif defined(__GNUC__)\r
160         #define BASE            r8\r
161 #else\r
162         #define BASE            rsp\r
163 #endif\r
164 \r
165 #define RA0(i, edx, edi)                \\r
166         AS2(    add edx, [Kt(i)]        )\\r
167         AS2(    add edx, [Wt(i)]        )\\r
168         AS2(    add edx, H(i)           )\\r
169 \r
170 #define RA1(i, edx, edi)\r
171 \r
172 #define RB0(i, edx, edi)\r
173 \r
174 #define RB1(i, edx, edi)        \\r
175         AS2(    mov AS_REG_7d, [Wt_2(i)]        )\\r
176         AS2(    mov edi, [Wt_15(i)])\\r
177         AS2(    mov ebx, AS_REG_7d      )\\r
178         AS2(    shr AS_REG_7d, 10               )\\r
179         AS2(    ror ebx, 17             )\\r
180         AS2(    xor AS_REG_7d, ebx      )\\r
181         AS2(    ror ebx, 2              )\\r
182         AS2(    xor ebx, AS_REG_7d      )/* s1(W_t-2) */\\r
183         AS2(    add ebx, [Wt_7(i)])\\r
184         AS2(    mov AS_REG_7d, edi      )\\r
185         AS2(    shr AS_REG_7d, 3                )\\r
186         AS2(    ror edi, 7              )\\r
187         AS2(    add ebx, [Wt(i)])/* s1(W_t-2) + W_t-7 + W_t-16 */\\r
188         AS2(    xor AS_REG_7d, edi      )\\r
189         AS2(    add edx, [Kt(i)])\\r
190         AS2(    ror edi, 11             )\\r
191         AS2(    add edx, H(i)   )\\r
192         AS2(    xor AS_REG_7d, edi      )/* s0(W_t-15) */\\r
193         AS2(    add AS_REG_7d, ebx      )/* W_t = s1(W_t-2) + W_t-7 + s0(W_t-15) W_t-16*/\\r
194         AS2(    mov [Wt(i)], AS_REG_7d)\\r
195         AS2(    add edx, AS_REG_7d      )\\r
196 \r
197 #define ROUND(i, r, eax, ecx, edi, edx)\\r
198         /* in: edi = E  */\\r
199         /* unused: eax, ecx, temp: ebx, AS_REG_7d, out: edx = T1 */\\r
200         AS2(    mov edx, F(i)   )\\r
201         AS2(    xor edx, G(i)   )\\r
202         AS2(    and edx, edi    )\\r
203         AS2(    xor edx, G(i)   )/* Ch(E,F,G) = (G^(E&(F^G))) */\\r
204         AS2(    mov AS_REG_7d, edi      )\\r
205         AS2(    ror edi, 6              )\\r
206         AS2(    ror AS_REG_7d, 25               )\\r
207         RA##r(i, edx, edi               )/* H + Wt + Kt + Ch(E,F,G) */\\r
208         AS2(    xor AS_REG_7d, edi      )\\r
209         AS2(    ror edi, 5              )\\r
210         AS2(    xor AS_REG_7d, edi      )/* S1(E) */\\r
211         AS2(    add edx, AS_REG_7d      )/* T1 = S1(E) + Ch(E,F,G) + H + Wt + Kt */\\r
212         RB##r(i, edx, edi               )/* H + Wt + Kt + Ch(E,F,G) */\\r
213         /* in: ecx = A, eax = B^C, edx = T1 */\\r
214         /* unused: edx, temp: ebx, AS_REG_7d, out: eax = A, ecx = B^C, edx = E */\\r
215         AS2(    mov ebx, ecx    )\\r
216         AS2(    xor ecx, B(i)   )/* A^B */\\r
217         AS2(    and eax, ecx    )\\r
218         AS2(    xor eax, B(i)   )/* Maj(A,B,C) = B^((A^B)&(B^C) */\\r
219         AS2(    mov AS_REG_7d, ebx      )\\r
220         AS2(    ror ebx, 2              )\\r
221         AS2(    add eax, edx    )/* T1 + Maj(A,B,C) */\\r
222         AS2(    add edx, D(i)   )\\r
223         AS2(    mov D(i), edx   )\\r
224         AS2(    ror AS_REG_7d, 22               )\\r
225         AS2(    xor AS_REG_7d, ebx      )\\r
226         AS2(    ror ebx, 11             )\\r
227         AS2(    xor AS_REG_7d, ebx      )\\r
228         AS2(    add eax, AS_REG_7d      )/* T1 + S0(A) + Maj(A,B,C) */\\r
229         AS2(    mov H(i), eax   )\\r
230 \r
231 #define SWAP_COPY(i)            \\r
232         AS2(    mov             WORD_REG(bx), [WORD_REG(dx)+i*WORD_SZ])\\r
233         AS1(    bswap   WORD_REG(bx))\\r
234         AS2(    mov             [Wt(i*(1+CRYPTOPP_BOOL_X64)+CRYPTOPP_BOOL_X64)], WORD_REG(bx))\r
235 \r
236 #if defined(__GNUC__)\r
237         #if CRYPTOPP_BOOL_X64\r
238                 FixedSizeAlignedSecBlock<byte, LOCALS_SIZE> workspace;\r
239         #endif\r
240         __asm__ __volatile__\r
241         (\r
242         #if CRYPTOPP_BOOL_X64\r
243                 "lea %4, %%r8;"\r
244         #endif\r
245         ".intel_syntax noprefix;"\r
246 #elif defined(CRYPTOPP_GENERATE_X64_MASM)\r
247                 ALIGN   8\r
248         X86_SHA256_HashBlocks   PROC FRAME\r
249                 rex_push_reg rsi\r
250                 push_reg rdi\r
251                 push_reg rbx\r
252                 push_reg rbp\r
253                 alloc_stack(LOCALS_SIZE+8)\r
254                 .endprolog\r
255                 mov rdi, r8\r
256                 lea rsi, [?SHA256_K@CryptoPP@@3QBIB + 48*4]\r
257 #endif\r
258 \r
259 #if CRYPTOPP_BOOL_X86\r
260         #ifndef __GNUC__\r
261                 AS2(    mov             edi, [len])\r
262                 AS2(    lea             WORD_REG(si), [SHA256_K+48*4])\r
263         #endif\r
264         #if !defined(_MSC_VER) || (_MSC_VER < 1400)\r
265                 AS_PUSH_IF86(bx)\r
266         #endif\r
267 \r
268         AS_PUSH_IF86(bp)\r
269         AS2(    mov             ebx, esp)\r
270         AS2(    and             esp, -16)\r
271         AS2(    sub             WORD_REG(sp), LOCALS_SIZE)\r
272         AS_PUSH_IF86(bx)\r
273 #endif\r
274         AS2(    mov             STATE_SAVE, WORD_REG(cx))\r
275         AS2(    mov             DATA_SAVE, WORD_REG(dx))\r
276         AS2(    add             WORD_REG(di), WORD_REG(dx))\r
277         AS2(    mov             DATA_END, WORD_REG(di))\r
278         AS2(    mov             K_END, WORD_REG(si))\r
279 \r
280 #if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE\r
281 #if CRYPTOPP_BOOL_X86\r
282         AS2(    test    edi, 1)\r
283         ASJ(    jnz,    2, f)\r
284 #endif\r
285         AS2(    movdqa  xmm0, XMMWORD_PTR [WORD_REG(cx)+0*16])\r
286         AS2(    movdqa  xmm1, XMMWORD_PTR [WORD_REG(cx)+1*16])\r
287 #endif\r
288 \r
289 #if CRYPTOPP_BOOL_X86\r
290 #if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE\r
291         ASJ(    jmp,    0, f)\r
292 #endif\r
293         ASL(2)  // non-SSE2\r
294         AS2(    mov             esi, ecx)\r
295         AS2(    lea             edi, A(0))\r
296         AS2(    mov             ecx, 8)\r
297         AS1(    rep movsd)\r
298         AS2(    mov             esi, K_END)\r
299         ASJ(    jmp,    3, f)\r
300 #endif\r
301 \r
302 #if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE\r
303         ASL(0)\r
304         AS2(    movdqa  E(0), xmm1)\r
305         AS2(    movdqa  A(0), xmm0)\r
306 #endif\r
307 #if CRYPTOPP_BOOL_X86\r
308         ASL(3)\r
309 #endif\r
310         AS2(    sub             WORD_REG(si), 48*4)\r
311         SWAP_COPY(0)    SWAP_COPY(1)    SWAP_COPY(2)    SWAP_COPY(3)\r
312         SWAP_COPY(4)    SWAP_COPY(5)    SWAP_COPY(6)    SWAP_COPY(7)\r
313 #if CRYPTOPP_BOOL_X86\r
314         SWAP_COPY(8)    SWAP_COPY(9)    SWAP_COPY(10)   SWAP_COPY(11)\r
315         SWAP_COPY(12)   SWAP_COPY(13)   SWAP_COPY(14)   SWAP_COPY(15)\r
316 #endif\r
317         AS2(    mov             edi, E(0))      // E\r
318         AS2(    mov             eax, B(0))      // B\r
319         AS2(    xor             eax, C(0))      // B^C\r
320         AS2(    mov             ecx, A(0))      // A\r
321 \r
322         ROUND(0, 0, eax, ecx, edi, edx)\r
323         ROUND(1, 0, ecx, eax, edx, edi)\r
324         ROUND(2, 0, eax, ecx, edi, edx)\r
325         ROUND(3, 0, ecx, eax, edx, edi)\r
326         ROUND(4, 0, eax, ecx, edi, edx)\r
327         ROUND(5, 0, ecx, eax, edx, edi)\r
328         ROUND(6, 0, eax, ecx, edi, edx)\r
329         ROUND(7, 0, ecx, eax, edx, edi)\r
330         ROUND(8, 0, eax, ecx, edi, edx)\r
331         ROUND(9, 0, ecx, eax, edx, edi)\r
332         ROUND(10, 0, eax, ecx, edi, edx)\r
333         ROUND(11, 0, ecx, eax, edx, edi)\r
334         ROUND(12, 0, eax, ecx, edi, edx)\r
335         ROUND(13, 0, ecx, eax, edx, edi)\r
336         ROUND(14, 0, eax, ecx, edi, edx)\r
337         ROUND(15, 0, ecx, eax, edx, edi)\r
338 \r
339         ASL(1)\r
340         AS2(add WORD_REG(si), 4*16)\r
341         ROUND(0, 1, eax, ecx, edi, edx)\r
342         ROUND(1, 1, ecx, eax, edx, edi)\r
343         ROUND(2, 1, eax, ecx, edi, edx)\r
344         ROUND(3, 1, ecx, eax, edx, edi)\r
345         ROUND(4, 1, eax, ecx, edi, edx)\r
346         ROUND(5, 1, ecx, eax, edx, edi)\r
347         ROUND(6, 1, eax, ecx, edi, edx)\r
348         ROUND(7, 1, ecx, eax, edx, edi)\r
349         ROUND(8, 1, eax, ecx, edi, edx)\r
350         ROUND(9, 1, ecx, eax, edx, edi)\r
351         ROUND(10, 1, eax, ecx, edi, edx)\r
352         ROUND(11, 1, ecx, eax, edx, edi)\r
353         ROUND(12, 1, eax, ecx, edi, edx)\r
354         ROUND(13, 1, ecx, eax, edx, edi)\r
355         ROUND(14, 1, eax, ecx, edi, edx)\r
356         ROUND(15, 1, ecx, eax, edx, edi)\r
357         AS2(    cmp             WORD_REG(si), K_END)\r
358         ASJ(    jne,    1, b)\r
359 \r
360         AS2(    mov             WORD_REG(dx), DATA_SAVE)\r
361         AS2(    add             WORD_REG(dx), 64)\r
362         AS2(    mov             AS_REG_7, STATE_SAVE)\r
363         AS2(    mov             DATA_SAVE, WORD_REG(dx))\r
364 \r
365 #if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE\r
366 #if CRYPTOPP_BOOL_X86\r
367         AS2(    test    DWORD PTR DATA_END, 1)\r
368         ASJ(    jnz,    4, f)\r
369 #endif\r
370         AS2(    movdqa  xmm1, XMMWORD_PTR [AS_REG_7+1*16])\r
371         AS2(    movdqa  xmm0, XMMWORD_PTR [AS_REG_7+0*16])\r
372         AS2(    paddd   xmm1, E(0))\r
373         AS2(    paddd   xmm0, A(0))\r
374         AS2(    movdqa  [AS_REG_7+1*16], xmm1)\r
375         AS2(    movdqa  [AS_REG_7+0*16], xmm0)\r
376         AS2(    cmp             WORD_REG(dx), DATA_END)\r
377         ASJ(    jl,             0, b)\r
378 #endif\r
379 \r
380 #if CRYPTOPP_BOOL_X86\r
381 #if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE\r
382         ASJ(    jmp,    5, f)\r
383         ASL(4)  // non-SSE2\r
384 #endif\r
385         AS2(    add             [AS_REG_7+0*4], ecx)    // A\r
386         AS2(    add             [AS_REG_7+4*4], edi)    // E\r
387         AS2(    mov             eax, B(0))\r
388         AS2(    mov             ebx, C(0))\r
389         AS2(    mov             ecx, D(0))\r
390         AS2(    add             [AS_REG_7+1*4], eax)\r
391         AS2(    add             [AS_REG_7+2*4], ebx)\r
392         AS2(    add             [AS_REG_7+3*4], ecx)\r
393         AS2(    mov             eax, F(0))\r
394         AS2(    mov             ebx, G(0))\r
395         AS2(    mov             ecx, H(0))\r
396         AS2(    add             [AS_REG_7+5*4], eax)\r
397         AS2(    add             [AS_REG_7+6*4], ebx)\r
398         AS2(    add             [AS_REG_7+7*4], ecx)\r
399         AS2(    mov             ecx, AS_REG_7d)\r
400         AS2(    cmp             WORD_REG(dx), DATA_END)\r
401         ASJ(    jl,             2, b)\r
402 #if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE\r
403         ASL(5)\r
404 #endif\r
405 #endif\r
406 \r
407         AS_POP_IF86(sp)\r
408         AS_POP_IF86(bp)\r
409         #if !defined(_MSC_VER) || (_MSC_VER < 1400)\r
410                 AS_POP_IF86(bx)\r
411         #endif\r
412 \r
413 #ifdef CRYPTOPP_GENERATE_X64_MASM\r
414         add             rsp, LOCALS_SIZE+8\r
415         pop             rbp\r
416         pop             rbx\r
417         pop             rdi\r
418         pop             rsi\r
419         ret\r
420         X86_SHA256_HashBlocks ENDP\r
421 #endif\r
422 \r
423 #ifdef __GNUC__\r
424         ".att_syntax prefix;"\r
425         : \r
426         : "c" (state), "d" (data), "S" (SHA256_K+48), "D" (len)\r
427         #if CRYPTOPP_BOOL_X64\r
428                 , "m" (workspace[0])\r
429         #endif\r
430         : "memory", "cc", "%eax"\r
431         #if CRYPTOPP_BOOL_X64\r
432                 , "%rbx", "%r8"\r
433         #endif\r
434         );\r
435 #endif\r
436 }\r
437 \r
438 #endif  // #if defined(CRYPTOPP_X86_ASM_AVAILABLE) || defined(CRYPTOPP_GENERATE_X64_MASM)\r
439 \r
440 #ifndef CRYPTOPP_GENERATE_X64_MASM\r
441 \r
442 #ifdef CRYPTOPP_X64_MASM_AVAILABLE\r
443 extern "C" {\r
444 void CRYPTOPP_FASTCALL X86_SHA256_HashBlocks(word32 *state, const word32 *data, size_t len);\r
445 }\r
446 #endif\r
447 \r
448 #if defined(CRYPTOPP_X86_ASM_AVAILABLE) || defined(CRYPTOPP_X64_MASM_AVAILABLE)\r
449 \r
450 size_t SHA256::HashMultipleBlocks(const word32 *input, size_t length)\r
451 {\r
452         X86_SHA256_HashBlocks(m_state, input, (length&(size_t(0)-BLOCKSIZE)) - !HasSSE2());\r
453         return length % BLOCKSIZE;\r
454 }\r
455 \r
456 size_t SHA224::HashMultipleBlocks(const word32 *input, size_t length)\r
457 {\r
458         X86_SHA256_HashBlocks(m_state, input, (length&(size_t(0)-BLOCKSIZE)) - !HasSSE2());\r
459         return length % BLOCKSIZE;\r
460 }\r
461 \r
462 #endif\r
463 \r
464 #define blk2(i) (W[i&15]+=s1(W[(i-2)&15])+W[(i-7)&15]+s0(W[(i-15)&15]))\r
465 \r
466 #define Ch(x,y,z) (z^(x&(y^z)))\r
467 #define Maj(x,y,z) (y^((x^y)&(y^z)))\r
468 \r
469 #define a(i) T[(0-i)&7]\r
470 #define b(i) T[(1-i)&7]\r
471 #define c(i) T[(2-i)&7]\r
472 #define d(i) T[(3-i)&7]\r
473 #define e(i) T[(4-i)&7]\r
474 #define f(i) T[(5-i)&7]\r
475 #define g(i) T[(6-i)&7]\r
476 #define h(i) T[(7-i)&7]\r
477 \r
478 #define R(i) h(i)+=S1(e(i))+Ch(e(i),f(i),g(i))+SHA256_K[i+j]+(j?blk2(i):blk0(i));\\r
479         d(i)+=h(i);h(i)+=S0(a(i))+Maj(a(i),b(i),c(i))\r
480 \r
481 // for SHA256\r
482 #define S0(x) (rotrFixed(x,2)^rotrFixed(x,13)^rotrFixed(x,22))\r
483 #define S1(x) (rotrFixed(x,6)^rotrFixed(x,11)^rotrFixed(x,25))\r
484 #define s0(x) (rotrFixed(x,7)^rotrFixed(x,18)^(x>>3))\r
485 #define s1(x) (rotrFixed(x,17)^rotrFixed(x,19)^(x>>10))\r
486 \r
487 void SHA256::Transform(word32 *state, const word32 *data)\r
488 {\r
489         word32 W[16];\r
490 #if defined(CRYPTOPP_X86_ASM_AVAILABLE) || defined(CRYPTOPP_X64_MASM_AVAILABLE)\r
491         // this byte reverse is a waste of time, but this function is only called by MDC\r
492         ByteReverse(W, data, BLOCKSIZE);\r
493         X86_SHA256_HashBlocks(state, W, BLOCKSIZE - !HasSSE2());\r
494 #else\r
495         word32 T[8];\r
496     /* Copy context->state[] to working vars */\r
497         memcpy(T, state, sizeof(T));\r
498     /* 64 operations, partially loop unrolled */\r
499         for (unsigned int j=0; j<64; j+=16)\r
500         {\r
501                 R( 0); R( 1); R( 2); R( 3);\r
502                 R( 4); R( 5); R( 6); R( 7);\r
503                 R( 8); R( 9); R(10); R(11);\r
504                 R(12); R(13); R(14); R(15);\r
505         }\r
506     /* Add the working vars back into context.state[] */\r
507     state[0] += a(0);\r
508     state[1] += b(0);\r
509     state[2] += c(0);\r
510     state[3] += d(0);\r
511     state[4] += e(0);\r
512     state[5] += f(0);\r
513     state[6] += g(0);\r
514     state[7] += h(0);\r
515 #endif\r
516 }\r
517 \r
518 /* \r
519 // smaller but slower\r
520 void SHA256::Transform(word32 *state, const word32 *data)\r
521 {\r
522         word32 T[20];\r
523         word32 W[32];\r
524         unsigned int i = 0, j = 0;\r
525         word32 *t = T+8;\r
526 \r
527         memcpy(t, state, 8*4);\r
528         word32 e = t[4], a = t[0];\r
529 \r
530         do \r
531         {\r
532                 word32 w = data[j];\r
533                 W[j] = w;\r
534                 w += SHA256_K[j];\r
535                 w += t[7];\r
536                 w += S1(e);\r
537                 w += Ch(e, t[5], t[6]);\r
538                 e = t[3] + w;\r
539                 t[3] = t[3+8] = e;\r
540                 w += S0(t[0]);\r
541                 a = w + Maj(a, t[1], t[2]);\r
542                 t[-1] = t[7] = a;\r
543                 --t;\r
544                 ++j;\r
545                 if (j%8 == 0)\r
546                         t += 8;\r
547         } while (j<16);\r
548 \r
549         do\r
550         {\r
551                 i = j&0xf;\r
552                 word32 w = s1(W[i+16-2]) + s0(W[i+16-15]) + W[i] + W[i+16-7];\r
553                 W[i+16] = W[i] = w;\r
554                 w += SHA256_K[j];\r
555                 w += t[7];\r
556                 w += S1(e);\r
557                 w += Ch(e, t[5], t[6]);\r
558                 e = t[3] + w;\r
559                 t[3] = t[3+8] = e;\r
560                 w += S0(t[0]);\r
561                 a = w + Maj(a, t[1], t[2]);\r
562                 t[-1] = t[7] = a;\r
563 \r
564                 w = s1(W[(i+1)+16-2]) + s0(W[(i+1)+16-15]) + W[(i+1)] + W[(i+1)+16-7];\r
565                 W[(i+1)+16] = W[(i+1)] = w;\r
566                 w += SHA256_K[j+1];\r
567                 w += (t-1)[7];\r
568                 w += S1(e);\r
569                 w += Ch(e, (t-1)[5], (t-1)[6]);\r
570                 e = (t-1)[3] + w;\r
571                 (t-1)[3] = (t-1)[3+8] = e;\r
572                 w += S0((t-1)[0]);\r
573                 a = w + Maj(a, (t-1)[1], (t-1)[2]);\r
574                 (t-1)[-1] = (t-1)[7] = a;\r
575 \r
576                 t-=2;\r
577                 j+=2;\r
578                 if (j%8 == 0)\r
579                         t += 8;\r
580         } while (j<64);\r
581 \r
582     state[0] += a;\r
583     state[1] += t[1];\r
584     state[2] += t[2];\r
585     state[3] += t[3];\r
586     state[4] += e;\r
587     state[5] += t[5];\r
588     state[6] += t[6];\r
589     state[7] += t[7];\r
590 }\r
591 */\r
592 \r
593 #undef S0\r
594 #undef S1\r
595 #undef s0\r
596 #undef s1\r
597 #undef R\r
598 \r
599 // *************************************************************\r
600 \r
601 void SHA384::InitState(HashWordType *state)\r
602 {\r
603         static const word64 s[8] = {\r
604                 W64LIT(0xcbbb9d5dc1059ed8), W64LIT(0x629a292a367cd507),\r
605                 W64LIT(0x9159015a3070dd17), W64LIT(0x152fecd8f70e5939),\r
606                 W64LIT(0x67332667ffc00b31), W64LIT(0x8eb44a8768581511),\r
607                 W64LIT(0xdb0c2e0d64f98fa7), W64LIT(0x47b5481dbefa4fa4)};\r
608         memcpy(state, s, sizeof(s));\r
609 }\r
610 \r
611 void SHA512::InitState(HashWordType *state)\r
612 {\r
613         static const word64 s[8] = {\r
614                 W64LIT(0x6a09e667f3bcc908), W64LIT(0xbb67ae8584caa73b),\r
615                 W64LIT(0x3c6ef372fe94f82b), W64LIT(0xa54ff53a5f1d36f1),\r
616                 W64LIT(0x510e527fade682d1), W64LIT(0x9b05688c2b3e6c1f),\r
617                 W64LIT(0x1f83d9abfb41bd6b), W64LIT(0x5be0cd19137e2179)};\r
618         memcpy(state, s, sizeof(s));\r
619 }\r
620 \r
621 #if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE && CRYPTOPP_BOOL_X86\r
622 CRYPTOPP_ALIGN_DATA(16) static const word64 SHA512_K[80] CRYPTOPP_SECTION_ALIGN16 = {\r
623 #else\r
624 static const word64 SHA512_K[80] = {\r
625 #endif\r
626         W64LIT(0x428a2f98d728ae22), W64LIT(0x7137449123ef65cd),\r
627         W64LIT(0xb5c0fbcfec4d3b2f), W64LIT(0xe9b5dba58189dbbc),\r
628         W64LIT(0x3956c25bf348b538), W64LIT(0x59f111f1b605d019),\r
629         W64LIT(0x923f82a4af194f9b), W64LIT(0xab1c5ed5da6d8118),\r
630         W64LIT(0xd807aa98a3030242), W64LIT(0x12835b0145706fbe),\r
631         W64LIT(0x243185be4ee4b28c), W64LIT(0x550c7dc3d5ffb4e2),\r
632         W64LIT(0x72be5d74f27b896f), W64LIT(0x80deb1fe3b1696b1),\r
633         W64LIT(0x9bdc06a725c71235), W64LIT(0xc19bf174cf692694),\r
634         W64LIT(0xe49b69c19ef14ad2), W64LIT(0xefbe4786384f25e3),\r
635         W64LIT(0x0fc19dc68b8cd5b5), W64LIT(0x240ca1cc77ac9c65),\r
636         W64LIT(0x2de92c6f592b0275), W64LIT(0x4a7484aa6ea6e483),\r
637         W64LIT(0x5cb0a9dcbd41fbd4), W64LIT(0x76f988da831153b5),\r
638         W64LIT(0x983e5152ee66dfab), W64LIT(0xa831c66d2db43210),\r
639         W64LIT(0xb00327c898fb213f), W64LIT(0xbf597fc7beef0ee4),\r
640         W64LIT(0xc6e00bf33da88fc2), W64LIT(0xd5a79147930aa725),\r
641         W64LIT(0x06ca6351e003826f), W64LIT(0x142929670a0e6e70),\r
642         W64LIT(0x27b70a8546d22ffc), W64LIT(0x2e1b21385c26c926),\r
643         W64LIT(0x4d2c6dfc5ac42aed), W64LIT(0x53380d139d95b3df),\r
644         W64LIT(0x650a73548baf63de), W64LIT(0x766a0abb3c77b2a8),\r
645         W64LIT(0x81c2c92e47edaee6), W64LIT(0x92722c851482353b),\r
646         W64LIT(0xa2bfe8a14cf10364), W64LIT(0xa81a664bbc423001),\r
647         W64LIT(0xc24b8b70d0f89791), W64LIT(0xc76c51a30654be30),\r
648         W64LIT(0xd192e819d6ef5218), W64LIT(0xd69906245565a910),\r
649         W64LIT(0xf40e35855771202a), W64LIT(0x106aa07032bbd1b8),\r
650         W64LIT(0x19a4c116b8d2d0c8), W64LIT(0x1e376c085141ab53),\r
651         W64LIT(0x2748774cdf8eeb99), W64LIT(0x34b0bcb5e19b48a8),\r
652         W64LIT(0x391c0cb3c5c95a63), W64LIT(0x4ed8aa4ae3418acb),\r
653         W64LIT(0x5b9cca4f7763e373), W64LIT(0x682e6ff3d6b2b8a3),\r
654         W64LIT(0x748f82ee5defb2fc), W64LIT(0x78a5636f43172f60),\r
655         W64LIT(0x84c87814a1f0ab72), W64LIT(0x8cc702081a6439ec),\r
656         W64LIT(0x90befffa23631e28), W64LIT(0xa4506cebde82bde9),\r
657         W64LIT(0xbef9a3f7b2c67915), W64LIT(0xc67178f2e372532b),\r
658         W64LIT(0xca273eceea26619c), W64LIT(0xd186b8c721c0c207),\r
659         W64LIT(0xeada7dd6cde0eb1e), W64LIT(0xf57d4f7fee6ed178),\r
660         W64LIT(0x06f067aa72176fba), W64LIT(0x0a637dc5a2c898a6),\r
661         W64LIT(0x113f9804bef90dae), W64LIT(0x1b710b35131c471b),\r
662         W64LIT(0x28db77f523047d84), W64LIT(0x32caab7b40c72493),\r
663         W64LIT(0x3c9ebe0a15c9bebc), W64LIT(0x431d67c49c100d4c),\r
664         W64LIT(0x4cc5d4becb3e42b6), W64LIT(0x597f299cfc657e2a),\r
665         W64LIT(0x5fcb6fab3ad6faec), W64LIT(0x6c44198c4a475817)\r
666 };\r
667 \r
668 #if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE && CRYPTOPP_BOOL_X86\r
669 // put assembly version in separate function, otherwise MSVC 2005 SP1 doesn't generate correct code for the non-assembly version\r
670 CRYPTOPP_NAKED static void CRYPTOPP_FASTCALL SHA512_SSE2_Transform(word64 *state, const word64 *data)\r
671 {\r
672 #ifdef __GNUC__\r
673         __asm__ __volatile__\r
674         (\r
675                 ".intel_syntax noprefix;"\r
676         AS1(    push    ebx)\r
677         AS2(    mov             ebx, eax)\r
678 #else\r
679         AS1(    push    ebx)\r
680         AS1(    push    esi)\r
681         AS1(    push    edi)\r
682         AS2(    lea             ebx, SHA512_K)\r
683 #endif\r
684 \r
685         AS2(    mov             eax, esp)\r
686         AS2(    and             esp, 0xfffffff0)\r
687         AS2(    sub             esp, 27*16)                             // 17*16 for expanded data, 20*8 for state\r
688         AS1(    push    eax)\r
689         AS2(    xor             eax, eax)\r
690         AS2(    lea             edi, [esp+4+8*8])               // start at middle of state buffer. will decrement pointer each round to avoid copying\r
691         AS2(    lea             esi, [esp+4+20*8+8])    // 16-byte alignment, then add 8\r
692 \r
693         AS2(    movdqa  xmm0, [ecx+0*16])\r
694         AS2(    movdq2q mm4, xmm0)\r
695         AS2(    movdqa  [edi+0*16], xmm0)\r
696         AS2(    movdqa  xmm0, [ecx+1*16])\r
697         AS2(    movdqa  [edi+1*16], xmm0)\r
698         AS2(    movdqa  xmm0, [ecx+2*16])\r
699         AS2(    movdq2q mm5, xmm0)\r
700         AS2(    movdqa  [edi+2*16], xmm0)\r
701         AS2(    movdqa  xmm0, [ecx+3*16])\r
702         AS2(    movdqa  [edi+3*16], xmm0)\r
703         ASJ(    jmp,    0, f)\r
704 \r
705 #define SSE2_S0_S1(r, a, b, c)  \\r
706         AS2(    movq    mm6, r)\\r
707         AS2(    psrlq   r, a)\\r
708         AS2(    movq    mm7, r)\\r
709         AS2(    psllq   mm6, 64-c)\\r
710         AS2(    pxor    mm7, mm6)\\r
711         AS2(    psrlq   r, b-a)\\r
712         AS2(    pxor    mm7, r)\\r
713         AS2(    psllq   mm6, c-b)\\r
714         AS2(    pxor    mm7, mm6)\\r
715         AS2(    psrlq   r, c-b)\\r
716         AS2(    pxor    r, mm7)\\r
717         AS2(    psllq   mm6, b-a)\\r
718         AS2(    pxor    r, mm6)\r
719 \r
720 #define SSE2_s0(r, a, b, c)     \\r
721         AS2(    movdqa  xmm6, r)\\r
722         AS2(    psrlq   r, a)\\r
723         AS2(    movdqa  xmm7, r)\\r
724         AS2(    psllq   xmm6, 64-c)\\r
725         AS2(    pxor    xmm7, xmm6)\\r
726         AS2(    psrlq   r, b-a)\\r
727         AS2(    pxor    xmm7, r)\\r
728         AS2(    psrlq   r, c-b)\\r
729         AS2(    pxor    r, xmm7)\\r
730         AS2(    psllq   xmm6, c-a)\\r
731         AS2(    pxor    r, xmm6)\r
732 \r
733 #define SSE2_s1(r, a, b, c)     \\r
734         AS2(    movdqa  xmm6, r)\\r
735         AS2(    psrlq   r, a)\\r
736         AS2(    movdqa  xmm7, r)\\r
737         AS2(    psllq   xmm6, 64-c)\\r
738         AS2(    pxor    xmm7, xmm6)\\r
739         AS2(    psrlq   r, b-a)\\r
740         AS2(    pxor    xmm7, r)\\r
741         AS2(    psllq   xmm6, c-b)\\r
742         AS2(    pxor    xmm7, xmm6)\\r
743         AS2(    psrlq   r, c-b)\\r
744         AS2(    pxor    r, xmm7)\r
745 \r
746         ASL(SHA512_Round)\r
747         // k + w is in mm0, a is in mm4, e is in mm5\r
748         AS2(    paddq   mm0, [edi+7*8])         // h\r
749         AS2(    movq    mm2, [edi+5*8])         // f\r
750         AS2(    movq    mm3, [edi+6*8])         // g\r
751         AS2(    pxor    mm2, mm3)\r
752         AS2(    pand    mm2, mm5)\r
753         SSE2_S0_S1(mm5,14,18,41)\r
754         AS2(    pxor    mm2, mm3)\r
755         AS2(    paddq   mm0, mm2)                       // h += Ch(e,f,g)\r
756         AS2(    paddq   mm5, mm0)                       // h += S1(e)\r
757         AS2(    movq    mm2, [edi+1*8])         // b\r
758         AS2(    movq    mm1, mm2)\r
759         AS2(    por             mm2, mm4)\r
760         AS2(    pand    mm2, [edi+2*8])         // c\r
761         AS2(    pand    mm1, mm4)\r
762         AS2(    por             mm1, mm2)\r
763         AS2(    paddq   mm1, mm5)                       // temp = h + Maj(a,b,c)\r
764         AS2(    paddq   mm5, [edi+3*8])         // e = d + h\r
765         AS2(    movq    [edi+3*8], mm5)\r
766         AS2(    movq    [edi+11*8], mm5)\r
767         SSE2_S0_S1(mm4,28,34,39)                        // S0(a)\r
768         AS2(    paddq   mm4, mm1)                       // a = temp + S0(a)\r
769         AS2(    movq    [edi-8], mm4)\r
770         AS2(    movq    [edi+7*8], mm4)\r
771         AS1(    ret)\r
772 \r
773         // first 16 rounds\r
774         ASL(0)\r
775         AS2(    movq    mm0, [edx+eax*8])\r
776         AS2(    movq    [esi+eax*8], mm0)\r
777         AS2(    movq    [esi+eax*8+16*8], mm0)\r
778         AS2(    paddq   mm0, [ebx+eax*8])\r
779         ASC(    call,   SHA512_Round)\r
780         AS1(    inc             eax)\r
781         AS2(    sub             edi, 8)\r
782         AS2(    test    eax, 7)\r
783         ASJ(    jnz,    0, b)\r
784         AS2(    add             edi, 8*8)\r
785         AS2(    cmp             eax, 16)\r
786         ASJ(    jne,    0, b)\r
787 \r
788         // rest of the rounds\r
789         AS2(    movdqu  xmm0, [esi+(16-2)*8])\r
790         ASL(1)\r
791         // data expansion, W[i-2] already in xmm0\r
792         AS2(    movdqu  xmm3, [esi])\r
793         AS2(    paddq   xmm3, [esi+(16-7)*8])\r
794         AS2(    movdqa  xmm2, [esi+(16-15)*8])\r
795         SSE2_s1(xmm0, 6, 19, 61)\r
796         AS2(    paddq   xmm0, xmm3)\r
797         SSE2_s0(xmm2, 1, 7, 8)\r
798         AS2(    paddq   xmm0, xmm2)\r
799         AS2(    movdq2q mm0, xmm0)\r
800         AS2(    movhlps xmm1, xmm0)\r
801         AS2(    paddq   mm0, [ebx+eax*8])\r
802         AS2(    movlps  [esi], xmm0)\r
803         AS2(    movlps  [esi+8], xmm1)\r
804         AS2(    movlps  [esi+8*16], xmm0)\r
805         AS2(    movlps  [esi+8*17], xmm1)\r
806         // 2 rounds\r
807         ASC(    call,   SHA512_Round)\r
808         AS2(    sub             edi, 8)\r
809         AS2(    movdq2q mm0, xmm1)\r
810         AS2(    paddq   mm0, [ebx+eax*8+8])\r
811         ASC(    call,   SHA512_Round)\r
812         // update indices and loop\r
813         AS2(    add             esi, 16)\r
814         AS2(    add             eax, 2)\r
815         AS2(    sub             edi, 8)\r
816         AS2(    test    eax, 7)\r
817         ASJ(    jnz,    1, b)\r
818         // do housekeeping every 8 rounds\r
819         AS2(    mov             esi, 0xf)\r
820         AS2(    and             esi, eax)\r
821         AS2(    lea             esi, [esp+4+20*8+8+esi*8])\r
822         AS2(    add             edi, 8*8)\r
823         AS2(    cmp             eax, 80)\r
824         ASJ(    jne,    1, b)\r
825 \r
826 #define SSE2_CombineState(i)    \\r
827         AS2(    movdqa  xmm0, [edi+i*16])\\r
828         AS2(    paddq   xmm0, [ecx+i*16])\\r
829         AS2(    movdqa  [ecx+i*16], xmm0)\r
830 \r
831         SSE2_CombineState(0)\r
832         SSE2_CombineState(1)\r
833         SSE2_CombineState(2)\r
834         SSE2_CombineState(3)\r
835 \r
836         AS1(    pop             esp)\r
837         AS1(    emms)\r
838 \r
839 #if defined(__GNUC__)\r
840         AS1(    pop             ebx)\r
841         ".att_syntax prefix;"\r
842                 :\r
843                 : "a" (SHA512_K), "c" (state), "d" (data)\r
844                 : "%esi", "%edi", "memory", "cc"\r
845         );\r
846 #else\r
847         AS1(    pop             edi)\r
848         AS1(    pop             esi)\r
849         AS1(    pop             ebx)\r
850         AS1(    ret)\r
851 #endif\r
852 }\r
853 #endif  // #if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE\r
854 \r
855 void SHA512::Transform(word64 *state, const word64 *data)\r
856 {\r
857 #if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE && CRYPTOPP_BOOL_X86\r
858         if (HasSSE2())\r
859         {\r
860                 SHA512_SSE2_Transform(state, data);\r
861                 return;\r
862         }\r
863 #endif\r
864 \r
865 #define S0(x) (rotrFixed(x,28)^rotrFixed(x,34)^rotrFixed(x,39))\r
866 #define S1(x) (rotrFixed(x,14)^rotrFixed(x,18)^rotrFixed(x,41))\r
867 #define s0(x) (rotrFixed(x,1)^rotrFixed(x,8)^(x>>7))\r
868 #define s1(x) (rotrFixed(x,19)^rotrFixed(x,61)^(x>>6))\r
869 \r
870 #define R(i) h(i)+=S1(e(i))+Ch(e(i),f(i),g(i))+SHA512_K[i+j]+(j?blk2(i):blk0(i));\\r
871         d(i)+=h(i);h(i)+=S0(a(i))+Maj(a(i),b(i),c(i))\r
872 \r
873         word64 W[16];\r
874         word64 T[8];\r
875     /* Copy context->state[] to working vars */\r
876         memcpy(T, state, sizeof(T));\r
877     /* 80 operations, partially loop unrolled */\r
878         for (unsigned int j=0; j<80; j+=16)\r
879         {\r
880                 R( 0); R( 1); R( 2); R( 3);\r
881                 R( 4); R( 5); R( 6); R( 7);\r
882                 R( 8); R( 9); R(10); R(11);\r
883                 R(12); R(13); R(14); R(15);\r
884         }\r
885     /* Add the working vars back into context.state[] */\r
886     state[0] += a(0);\r
887     state[1] += b(0);\r
888     state[2] += c(0);\r
889     state[3] += d(0);\r
890     state[4] += e(0);\r
891     state[5] += f(0);\r
892     state[6] += g(0);\r
893     state[7] += h(0);\r
894 }\r
895 \r
896 NAMESPACE_END\r
897 \r
898 #endif  // #ifndef CRYPTOPP_GENERATE_X64_MASM\r
899 #endif  // #ifndef CRYPTOPP_IMPORTS\r