9a37cf3dd1462a9a1a2e5035971d6b0cf172a672
[novacoin.git] / src / crypto / sha2 / asm / sha256_sse4.asm
1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2 ; Copyright (c) 2012, Intel Corporation 
3
4 ; All rights reserved. 
5
6 ; Redistribution and use in source and binary forms, with or without
7 ; modification, are permitted provided that the following conditions are
8 ; met: 
9
10 ; * Redistributions of source code must retain the above copyright
11 ;   notice, this list of conditions and the following disclaimer.  
12
13 ; * Redistributions in binary form must reproduce the above copyright
14 ;   notice, this list of conditions and the following disclaimer in the
15 ;   documentation and/or other materials provided with the
16 ;   distribution. 
17
18 ; * Neither the name of the Intel Corporation nor the names of its
19 ;   contributors may be used to endorse or promote products derived from
20 ;   this software without specific prior written permission. 
21
22
23 ; THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION "AS IS" AND ANY
24 ; EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 ; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
26 ; PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL CORPORATION OR
27 ; CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
28 ; EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
29 ; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30 ; PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31 ; LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32 ; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33 ; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
35 ;
36 ; Example YASM command lines:
37 ; Windows:  yasm -Xvc -f x64 -rnasm -pnasm -o sha256_sse4.obj -g cv8 sha256_sse4.asm
38 ; Linux:    yasm -f x64 -f elf64 -X gnu -g dwarf2 -D LINUX -o sha256_sse4.o sha256_sse4.asm
39 ;
40 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
41 ;
42 ; This code is described in an Intel White-Paper:
43 ; "Fast SHA-256 Implementations on Intel Architecture Processors"
44 ;
45 ; To find it, surf to http://www.intel.com/p/en_US/embedded 
46 ; and search for that title.
47 ; The paper is expected to be released roughly at the end of April, 2012
48 ;
49 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
50 ; This code schedules 1 blocks at a time, with 4 lanes per block
51 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
52
53 %define    MOVDQ movdqu ;; assume buffers not aligned 
54
55 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Define Macros
56
57 ; addm [mem], reg
58 ; Add reg to mem using reg-mem add and store
59 %macro addm 2
60     add    %2, %1
61     mov    %1, %2
62 %endm
63
64 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
65
66 ; COPY_XMM_AND_BSWAP xmm, [mem], byte_flip_mask
67 ; Load xmm with mem and byte swap each dword
68 %macro COPY_XMM_AND_BSWAP 3
69     MOVDQ %1, %2
70     pshufb %1, %3
71 %endmacro
72
73 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
74
75 %define X0 xmm4
76 %define X1 xmm5
77 %define X2 xmm6
78 %define X3 xmm7
79
80 %define XTMP0 xmm0
81 %define XTMP1 xmm1
82 %define XTMP2 xmm2
83 %define XTMP3 xmm3
84 %define XTMP4 xmm8
85 %define XFER  xmm9
86
87 %define SHUF_00BA    xmm10 ; shuffle xBxA -> 00BA
88 %define SHUF_DC00    xmm11 ; shuffle xDxC -> DC00
89 %define BYTE_FLIP_MASK    xmm12
90     
91 %ifdef LINUX
92 %define NUM_BLKS rdx    ; 3rd arg
93 %define CTX    rsi    ; 2nd arg
94 %define INP    rdi    ; 1st arg
95
96 %define SRND    rdi    ; clobbers INP
97 %define c    ecx
98 %define d     r8d
99 %define e     edx
100 %else
101 %define NUM_BLKS r8    ; 3rd arg
102 %define CTX    rdx     ; 2nd arg
103 %define INP    rcx     ; 1st arg
104
105 %define SRND    rcx    ; clobbers INP
106 %define c     edi 
107 %define d    esi 
108 %define e     r8d
109     
110 %endif
111 %define TBL    rbp
112 %define a eax
113 %define b ebx
114
115 %define f r9d
116 %define g r10d
117 %define h r11d
118
119 %define y0 r13d
120 %define y1 r14d
121 %define y2 r15d
122
123
124
125 _INP_END_SIZE    equ 8
126 _INP_SIZE    equ 8
127 _XFER_SIZE    equ 8
128 %ifdef LINUX
129 _XMM_SAVE_SIZE    equ 0
130 %else
131 _XMM_SAVE_SIZE    equ 7*16
132 %endif
133 ; STACK_SIZE plus pushes must be an odd multiple of 8
134 _ALIGN_SIZE    equ 8
135
136 _INP_END    equ 0
137 _INP        equ _INP_END  + _INP_END_SIZE
138 _XFER        equ _INP      + _INP_SIZE
139 _XMM_SAVE    equ _XFER     + _XFER_SIZE + _ALIGN_SIZE
140 STACK_SIZE    equ _XMM_SAVE + _XMM_SAVE_SIZE
141
142 ; rotate_Xs
143 ; Rotate values of symbols X0...X3
144 %macro rotate_Xs 0
145 %xdefine X_ X0
146 %xdefine X0 X1
147 %xdefine X1 X2
148 %xdefine X2 X3
149 %xdefine X3 X_
150 %endm
151
152 ; ROTATE_ARGS
153 ; Rotate values of symbols a...h
154 %macro ROTATE_ARGS 0
155 %xdefine TMP_ h
156 %xdefine h g
157 %xdefine g f
158 %xdefine f e
159 %xdefine e d
160 %xdefine d c
161 %xdefine c b
162 %xdefine b a
163 %xdefine a TMP_
164 %endm
165
166 %macro FOUR_ROUNDS_AND_SCHED 0
167     ;; compute s0 four at a time and s1 two at a time
168     ;; compute W[-16] + W[-7] 4 at a time
169     movdqa    XTMP0, X3
170     mov    y0, e        ; y0 = e
171     ror    y0, (25-11)    ; y0 = e >> (25-11)
172     mov    y1, a        ; y1 = a
173     palignr    XTMP0, X2, 4    ; XTMP0 = W[-7]
174     ror    y1, (22-13)    ; y1 = a >> (22-13)
175     xor    y0, e        ; y0 = e ^ (e >> (25-11))
176     mov    y2, f        ; y2 = f
177     ror    y0, (11-6)    ; y0 = (e >> (11-6)) ^ (e >> (25-6))
178     movdqa    XTMP1, X1
179     xor    y1, a        ; y1 = a ^ (a >> (22-13)
180     xor    y2, g        ; y2 = f^g
181     paddd    XTMP0, X0    ; XTMP0 = W[-7] + W[-16]
182     xor    y0, e        ; y0 = e ^ (e >> (11-6)) ^ (e >> (25-6))
183     and    y2, e        ; y2 = (f^g)&e
184     ror    y1, (13-2)    ; y1 = (a >> (13-2)) ^ (a >> (22-2))
185     ;; compute s0
186     palignr    XTMP1, X0, 4    ; XTMP1 = W[-15]
187     xor    y1, a        ; y1 = a ^ (a >> (13-2)) ^ (a >> (22-2))
188     ror    y0, 6        ; y0 = S1 = (e>>6) & (e>>11) ^ (e>>25)
189     xor    y2, g        ; y2 = CH = ((f^g)&e)^g
190     movdqa    XTMP2, XTMP1    ; XTMP2 = W[-15]
191     ror    y1, 2        ; y1 = S0 = (a>>2) ^ (a>>13) ^ (a>>22)
192     add    y2, y0        ; y2 = S1 + CH
193     add    y2, [rsp + _XFER + 0*4]    ; y2 = k + w + S1 + CH
194     movdqa    XTMP3, XTMP1    ; XTMP3 = W[-15]
195     mov    y0, a        ; y0 = a
196     add    h, y2        ; h = h + S1 + CH + k + w
197     mov    y2, a        ; y2 = a
198     pslld    XTMP1, (32-7)
199     or    y0, c        ; y0 = a|c
200     add    d, h        ; d = d + h + S1 + CH + k + w
201     and    y2, c        ; y2 = a&c
202     psrld    XTMP2, 7
203     and    y0, b        ; y0 = (a|c)&b
204     add    h, y1        ; h = h + S1 + CH + k + w + S0
205     por    XTMP1, XTMP2    ; XTMP1 = W[-15] ror 7
206     or    y0, y2        ; y0 = MAJ = (a|c)&b)|(a&c)
207     add    h, y0        ; h = h + S1 + CH + k + w + S0 + MAJ
208
209 ROTATE_ARGS
210     movdqa    XTMP2, XTMP3    ; XTMP2 = W[-15]
211     mov    y0, e        ; y0 = e
212     mov    y1, a        ; y1 = a
213     movdqa    XTMP4, XTMP3    ; XTMP4 = W[-15]
214     ror    y0, (25-11)    ; y0 = e >> (25-11)
215     xor    y0, e        ; y0 = e ^ (e >> (25-11))
216     mov    y2, f        ; y2 = f
217     ror    y1, (22-13)    ; y1 = a >> (22-13)
218     pslld    XTMP3, (32-18)
219     xor    y1, a        ; y1 = a ^ (a >> (22-13)
220     ror    y0, (11-6)    ; y0 = (e >> (11-6)) ^ (e >> (25-6))
221     xor    y2, g        ; y2 = f^g
222     psrld    XTMP2, 18
223     ror    y1, (13-2)    ; y1 = (a >> (13-2)) ^ (a >> (22-2))
224     xor    y0, e        ; y0 = e ^ (e >> (11-6)) ^ (e >> (25-6))
225     and    y2, e        ; y2 = (f^g)&e
226     ror    y0, 6        ; y0 = S1 = (e>>6) & (e>>11) ^ (e>>25)
227     pxor    XTMP1, XTMP3
228     xor    y1, a        ; y1 = a ^ (a >> (13-2)) ^ (a >> (22-2))
229     xor    y2, g        ; y2 = CH = ((f^g)&e)^g
230     psrld    XTMP4, 3    ; XTMP4 = W[-15] >> 3
231     add    y2, y0        ; y2 = S1 + CH
232     add    y2, [rsp + _XFER + 1*4]    ; y2 = k + w + S1 + CH
233     ror    y1, 2        ; y1 = S0 = (a>>2) ^ (a>>13) ^ (a>>22)
234     pxor    XTMP1, XTMP2    ; XTMP1 = W[-15] ror 7 ^ W[-15] ror 18
235     mov    y0, a        ; y0 = a
236     add    h, y2        ; h = h + S1 + CH + k + w
237     mov    y2, a        ; y2 = a
238     pxor    XTMP1, XTMP4    ; XTMP1 = s0
239     or    y0, c        ; y0 = a|c
240     add    d, h        ; d = d + h + S1 + CH + k + w
241     and    y2, c        ; y2 = a&c
242     ;; compute low s1
243     pshufd    XTMP2, X3, 11111010b    ; XTMP2 = W[-2] {BBAA}
244     and    y0, b        ; y0 = (a|c)&b
245     add    h, y1        ; h = h + S1 + CH + k + w + S0
246     paddd    XTMP0, XTMP1    ; XTMP0 = W[-16] + W[-7] + s0
247     or    y0, y2        ; y0 = MAJ = (a|c)&b)|(a&c)
248     add    h, y0        ; h = h + S1 + CH + k + w + S0 + MAJ
249
250 ROTATE_ARGS
251     movdqa    XTMP3, XTMP2    ; XTMP3 = W[-2] {BBAA}
252     mov    y0, e        ; y0 = e
253     mov    y1, a        ; y1 = a
254     ror    y0, (25-11)    ; y0 = e >> (25-11)
255     movdqa    XTMP4, XTMP2    ; XTMP4 = W[-2] {BBAA}
256     xor    y0, e        ; y0 = e ^ (e >> (25-11))
257     ror    y1, (22-13)    ; y1 = a >> (22-13)
258     mov    y2, f        ; y2 = f
259     xor    y1, a        ; y1 = a ^ (a >> (22-13)
260     ror    y0, (11-6)    ; y0 = (e >> (11-6)) ^ (e >> (25-6))
261     psrlq    XTMP2, 17    ; XTMP2 = W[-2] ror 17 {xBxA}
262     xor    y2, g        ; y2 = f^g
263     psrlq    XTMP3, 19    ; XTMP3 = W[-2] ror 19 {xBxA}
264     xor    y0, e        ; y0 = e ^ (e >> (11-6)) ^ (e >> (25-6))
265     and    y2, e        ; y2 = (f^g)&e
266     psrld    XTMP4, 10    ; XTMP4 = W[-2] >> 10 {BBAA}
267     ror    y1, (13-2)    ; y1 = (a >> (13-2)) ^ (a >> (22-2))
268     xor    y1, a        ; y1 = a ^ (a >> (13-2)) ^ (a >> (22-2))
269     xor    y2, g        ; y2 = CH = ((f^g)&e)^g
270     ror    y0, 6        ; y0 = S1 = (e>>6) & (e>>11) ^ (e>>25)
271     pxor    XTMP2, XTMP3
272     add    y2, y0        ; y2 = S1 + CH
273     ror    y1, 2        ; y1 = S0 = (a>>2) ^ (a>>13) ^ (a>>22)
274     add    y2, [rsp + _XFER + 2*4]    ; y2 = k + w + S1 + CH
275     pxor    XTMP4, XTMP2    ; XTMP4 = s1 {xBxA}
276     mov    y0, a        ; y0 = a
277     add    h, y2        ; h = h + S1 + CH + k + w
278     mov    y2, a        ; y2 = a
279     pshufb    XTMP4, SHUF_00BA    ; XTMP4 = s1 {00BA}
280     or    y0, c        ; y0 = a|c
281     add    d, h        ; d = d + h + S1 + CH + k + w
282     and    y2, c        ; y2 = a&c
283     paddd    XTMP0, XTMP4    ; XTMP0 = {..., ..., W[1], W[0]}
284     and    y0, b        ; y0 = (a|c)&b
285     add    h, y1        ; h = h + S1 + CH + k + w + S0
286     ;; compute high s1
287     pshufd    XTMP2, XTMP0, 01010000b    ; XTMP2 = W[-2] {DDCC}
288     or    y0, y2        ; y0 = MAJ = (a|c)&b)|(a&c)
289     add    h, y0        ; h = h + S1 + CH + k + w + S0 + MAJ
290
291 ROTATE_ARGS
292     movdqa    XTMP3, XTMP2    ; XTMP3 = W[-2] {DDCC}
293     mov    y0, e        ; y0 = e
294     ror    y0, (25-11)    ; y0 = e >> (25-11)
295     mov    y1, a        ; y1 = a
296     movdqa    X0,    XTMP2    ; X0    = W[-2] {DDCC}
297     ror    y1, (22-13)    ; y1 = a >> (22-13)
298     xor    y0, e        ; y0 = e ^ (e >> (25-11))
299     mov    y2, f        ; y2 = f
300     ror    y0, (11-6)    ; y0 = (e >> (11-6)) ^ (e >> (25-6))
301     psrlq    XTMP2, 17    ; XTMP2 = W[-2] ror 17 {xDxC}
302     xor    y1, a        ; y1 = a ^ (a >> (22-13)
303     xor    y2, g        ; y2 = f^g
304     psrlq    XTMP3, 19    ; XTMP3 = W[-2] ror 19 {xDxC}
305     xor    y0, e        ; y0 = e ^ (e >> (11-6)) ^ (e >> (25-6))
306     and    y2, e        ; y2 = (f^g)&e
307     ror    y1, (13-2)    ; y1 = (a >> (13-2)) ^ (a >> (22-2))
308     psrld    X0,    10    ; X0 = W[-2] >> 10 {DDCC}
309     xor    y1, a        ; y1 = a ^ (a >> (13-2)) ^ (a >> (22-2))
310     ror    y0, 6        ; y0 = S1 = (e>>6) & (e>>11) ^ (e>>25)
311     xor    y2, g        ; y2 = CH = ((f^g)&e)^g
312     pxor    XTMP2, XTMP3
313     ror    y1, 2        ; y1 = S0 = (a>>2) ^ (a>>13) ^ (a>>22)
314     add    y2, y0        ; y2 = S1 + CH
315     add    y2, [rsp + _XFER + 3*4]    ; y2 = k + w + S1 + CH
316     pxor    X0, XTMP2    ; X0 = s1 {xDxC}
317     mov    y0, a        ; y0 = a
318     add    h, y2        ; h = h + S1 + CH + k + w
319     mov    y2, a        ; y2 = a
320     pshufb    X0, SHUF_DC00    ; X0 = s1 {DC00}
321     or    y0, c        ; y0 = a|c
322     add    d, h        ; d = d + h + S1 + CH + k + w
323     and    y2, c        ; y2 = a&c
324     paddd    X0, XTMP0    ; X0 = {W[3], W[2], W[1], W[0]}
325     and    y0, b        ; y0 = (a|c)&b
326     add    h, y1        ; h = h + S1 + CH + k + w + S0
327     or    y0, y2        ; y0 = MAJ = (a|c)&b)|(a&c)
328     add    h, y0        ; h = h + S1 + CH + k + w + S0 + MAJ
329
330 ROTATE_ARGS
331 rotate_Xs
332 %endm
333
334 ;; input is [rsp + _XFER + %1 * 4]
335 %macro DO_ROUND 1
336     mov    y0, e        ; y0 = e
337     ror    y0, (25-11)    ; y0 = e >> (25-11)
338     mov    y1, a        ; y1 = a
339     xor    y0, e        ; y0 = e ^ (e >> (25-11))
340     ror    y1, (22-13)    ; y1 = a >> (22-13)
341     mov    y2, f        ; y2 = f
342     xor    y1, a        ; y1 = a ^ (a >> (22-13)
343     ror    y0, (11-6)    ; y0 = (e >> (11-6)) ^ (e >> (25-6))
344     xor    y2, g        ; y2 = f^g
345     xor    y0, e        ; y0 = e ^ (e >> (11-6)) ^ (e >> (25-6))
346     ror    y1, (13-2)    ; y1 = (a >> (13-2)) ^ (a >> (22-2))
347     and    y2, e        ; y2 = (f^g)&e
348     xor    y1, a        ; y1 = a ^ (a >> (13-2)) ^ (a >> (22-2))
349     ror    y0, 6        ; y0 = S1 = (e>>6) & (e>>11) ^ (e>>25)
350     xor    y2, g        ; y2 = CH = ((f^g)&e)^g
351     add    y2, y0        ; y2 = S1 + CH
352     ror    y1, 2        ; y1 = S0 = (a>>2) ^ (a>>13) ^ (a>>22)
353     add    y2, [rsp + _XFER + %1 * 4]    ; y2 = k + w + S1 + CH
354     mov    y0, a        ; y0 = a
355     add    h, y2        ; h = h + S1 + CH + k + w
356     mov    y2, a        ; y2 = a
357     or    y0, c        ; y0 = a|c
358     add    d, h        ; d = d + h + S1 + CH + k + w
359     and    y2, c        ; y2 = a&c
360     and    y0, b        ; y0 = (a|c)&b
361     add    h, y1        ; h = h + S1 + CH + k + w + S0
362     or    y0, y2        ; y0 = MAJ = (a|c)&b)|(a&c)
363     add    h, y0        ; h = h + S1 + CH + k + w + S0 + MAJ
364     ROTATE_ARGS
365 %endm
366
367 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
368 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
369 ;; void sha256_sse4(void *input_data, UINT32 digest[8], UINT64 num_blks)
370 ;; arg 1 : pointer to input data
371 ;; arg 2 : pointer to digest
372 ;; arg 3 : Num blocks
373 section .text
374 global sha256_sse4
375 align 32
376 sha256_sse4:
377     push    rbx
378 %ifndef LINUX
379     push    rsi
380     push    rdi
381 %endif
382     push    rbp
383     push    r13
384     push    r14
385     push    r15
386
387     sub    rsp,STACK_SIZE
388 %ifndef LINUX
389     movdqa    [rsp + _XMM_SAVE + 0*16],xmm6    
390     movdqa    [rsp + _XMM_SAVE + 1*16],xmm7
391     movdqa    [rsp + _XMM_SAVE + 2*16],xmm8    
392     movdqa    [rsp + _XMM_SAVE + 3*16],xmm9    
393     movdqa    [rsp + _XMM_SAVE + 4*16],xmm10
394     movdqa    [rsp + _XMM_SAVE + 5*16],xmm11
395     movdqa    [rsp + _XMM_SAVE + 6*16],xmm12
396 %endif
397
398     shl    NUM_BLKS, 6    ; convert to bytes
399     jz    done_hash
400     add    NUM_BLKS, INP    ; pointer to end of data
401     mov    [rsp + _INP_END], NUM_BLKS
402
403     ;; load initial digest
404     mov    a,[4*0 + CTX]
405     mov    b,[4*1 + CTX]
406     mov    c,[4*2 + CTX]
407     mov    d,[4*3 + CTX]
408     mov    e,[4*4 + CTX]
409     mov    f,[4*5 + CTX]
410     mov    g,[4*6 + CTX]
411     mov    h,[4*7 + CTX]
412
413     movdqa    BYTE_FLIP_MASK, [PSHUFFLE_BYTE_FLIP_MASK wrt rip]
414     movdqa    SHUF_00BA, [_SHUF_00BA wrt rip]
415     movdqa    SHUF_DC00, [_SHUF_DC00 wrt rip]
416
417 loop0:
418     lea    TBL,[K256 wrt rip]
419
420     ;; byte swap first 16 dwords
421     COPY_XMM_AND_BSWAP    X0, [INP + 0*16], BYTE_FLIP_MASK
422     COPY_XMM_AND_BSWAP    X1, [INP + 1*16], BYTE_FLIP_MASK
423     COPY_XMM_AND_BSWAP    X2, [INP + 2*16], BYTE_FLIP_MASK
424     COPY_XMM_AND_BSWAP    X3, [INP + 3*16], BYTE_FLIP_MASK
425     
426     mov    [rsp + _INP], INP
427
428     ;; schedule 48 input dwords, by doing 3 rounds of 16 each
429     mov    SRND, 3
430 align 16
431 loop1:
432     movdqa    XFER, [TBL + 0*16]
433     paddd    XFER, X0
434     movdqa    [rsp + _XFER], XFER
435     FOUR_ROUNDS_AND_SCHED
436
437     movdqa    XFER, [TBL + 1*16]
438     paddd    XFER, X0
439     movdqa    [rsp + _XFER], XFER
440     FOUR_ROUNDS_AND_SCHED
441
442     movdqa    XFER, [TBL + 2*16]
443     paddd    XFER, X0
444     movdqa    [rsp + _XFER], XFER
445     FOUR_ROUNDS_AND_SCHED
446
447     movdqa    XFER, [TBL + 3*16]
448     paddd    XFER, X0
449     movdqa    [rsp + _XFER], XFER
450     add    TBL, 4*16
451     FOUR_ROUNDS_AND_SCHED
452
453     sub    SRND, 1
454     jne    loop1
455
456     mov    SRND, 2
457 loop2:
458     paddd    X0, [TBL + 0*16]
459     movdqa    [rsp + _XFER], X0
460     DO_ROUND    0
461     DO_ROUND    1
462     DO_ROUND    2
463     DO_ROUND    3
464     paddd    X1, [TBL + 1*16]
465     movdqa    [rsp + _XFER], X1
466     add    TBL, 2*16
467     DO_ROUND    0
468     DO_ROUND    1
469     DO_ROUND    2
470     DO_ROUND    3
471
472     movdqa    X0, X2
473     movdqa    X1, X3
474
475     sub    SRND, 1
476     jne    loop2
477
478     addm    [4*0 + CTX],a
479     addm    [4*1 + CTX],b
480     addm    [4*2 + CTX],c
481     addm    [4*3 + CTX],d
482     addm    [4*4 + CTX],e
483     addm    [4*5 + CTX],f
484     addm    [4*6 + CTX],g
485     addm    [4*7 + CTX],h
486
487     mov    INP, [rsp + _INP]
488     add    INP, 64
489     cmp    INP, [rsp + _INP_END]
490     jne    loop0
491
492 done_hash:
493 %ifndef LINUX
494     movdqa    xmm6,[rsp + _XMM_SAVE + 0*16]
495     movdqa    xmm7,[rsp + _XMM_SAVE + 1*16]
496     movdqa    xmm8,[rsp + _XMM_SAVE + 2*16]
497     movdqa    xmm9,[rsp + _XMM_SAVE + 3*16]
498     movdqa    xmm10,[rsp + _XMM_SAVE + 4*16]
499     movdqa    xmm11,[rsp + _XMM_SAVE + 5*16]
500     movdqa    xmm12,[rsp + _XMM_SAVE + 6*16]
501 %endif
502
503     add    rsp, STACK_SIZE
504
505     pop    r15
506     pop    r14
507     pop    r13
508     pop    rbp
509 %ifndef LINUX
510     pop    rdi
511     pop    rsi
512 %endif
513     pop    rbx
514
515     ret    
516     
517 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
518 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
519 ;; void sha256_sse4_swap(void *input_data, UINT32 digest[8], UINT64 num_blks)
520 ;; arg 1 : pointer to input data
521 ;; arg 2 : pointer to digest
522 ;; arg 3 : Num blocks
523 section .text
524 global sha256_sse4_swap
525 align 32
526 sha256_sse4_swap:
527     push    rbx
528 %ifndef LINUX
529     push    rsi
530     push    rdi
531 %endif
532     push    rbp
533     push    r13
534     push    r14
535     push    r15
536
537     sub    rsp,STACK_SIZE
538 %ifndef LINUX
539     movdqa    [rsp + _XMM_SAVE + 0*16],xmm6    
540     movdqa    [rsp + _XMM_SAVE + 1*16],xmm7
541     movdqa    [rsp + _XMM_SAVE + 2*16],xmm8    
542     movdqa    [rsp + _XMM_SAVE + 3*16],xmm9    
543     movdqa    [rsp + _XMM_SAVE + 4*16],xmm10
544     movdqa    [rsp + _XMM_SAVE + 5*16],xmm11
545     movdqa    [rsp + _XMM_SAVE + 6*16],xmm12
546 %endif
547
548     shl    NUM_BLKS, 6    ; convert to bytes
549     jz    done_hash_swap
550     add    NUM_BLKS, INP    ; pointer to end of data
551     mov    [rsp + _INP_END], NUM_BLKS
552
553     ;; load initial digest
554     mov    a,[4*0 + CTX]
555     mov    b,[4*1 + CTX]
556     mov    c,[4*2 + CTX]
557     mov    d,[4*3 + CTX]
558     mov    e,[4*4 + CTX]
559     mov    f,[4*5 + CTX]
560     mov    g,[4*6 + CTX]
561     mov    h,[4*7 + CTX]
562
563     movdqa    BYTE_FLIP_MASK, [PSHUFFLE_BYTE_FLIP_MASK wrt rip]
564     movdqa    SHUF_00BA, [_SHUF_00BA wrt rip]
565     movdqa    SHUF_DC00, [_SHUF_DC00 wrt rip]
566
567 loop0_swap:
568     lea    TBL,[K256 wrt rip]
569
570     ;; byte swap first 16 dwords
571     COPY_XMM_AND_BSWAP    X0, [INP + 0*16], BYTE_FLIP_MASK
572     COPY_XMM_AND_BSWAP    X1, [INP + 1*16], BYTE_FLIP_MASK
573     COPY_XMM_AND_BSWAP    X2, [INP + 2*16], BYTE_FLIP_MASK
574     COPY_XMM_AND_BSWAP    X3, [INP + 3*16], BYTE_FLIP_MASK
575     
576     mov    [rsp + _INP], INP
577
578     ;; schedule 48 input dwords, by doing 3 rounds of 16 each
579     mov    SRND, 3
580 align 16
581 loop1_swap:
582     movdqa    XFER, [TBL + 0*16]
583     paddd    XFER, X0
584     movdqa    [rsp + _XFER], XFER
585     FOUR_ROUNDS_AND_SCHED
586
587     movdqa    XFER, [TBL + 1*16]
588     paddd    XFER, X0
589     movdqa    [rsp + _XFER], XFER
590     FOUR_ROUNDS_AND_SCHED
591
592     movdqa    XFER, [TBL + 2*16]
593     paddd    XFER, X0
594     movdqa    [rsp + _XFER], XFER
595     FOUR_ROUNDS_AND_SCHED
596
597     movdqa    XFER, [TBL + 3*16]
598     paddd    XFER, X0
599     movdqa    [rsp + _XFER], XFER
600     add    TBL, 4*16
601     FOUR_ROUNDS_AND_SCHED
602
603     sub    SRND, 1
604     jne    loop1_swap
605
606     mov    SRND, 2
607 loop2_swap:
608     paddd    X0, [TBL + 0*16]
609     movdqa    [rsp + _XFER], X0
610     DO_ROUND    0
611     DO_ROUND    1
612     DO_ROUND    2
613     DO_ROUND    3
614     paddd    X1, [TBL + 1*16]
615     movdqa    [rsp + _XFER], X1
616     add    TBL, 2*16
617     DO_ROUND    0
618     DO_ROUND    1
619     DO_ROUND    2
620     DO_ROUND    3
621
622     movdqa    X0, X2
623     movdqa    X1, X3
624
625     sub    SRND, 1
626     jne    loop2_swap
627
628     addm    [4*0 + CTX],a
629     addm    [4*1 + CTX],b
630     addm    [4*2 + CTX],c
631     addm    [4*3 + CTX],d
632     addm    [4*4 + CTX],e
633     addm    [4*5 + CTX],f
634     addm    [4*6 + CTX],g
635     addm    [4*7 + CTX],h
636
637     mov    INP, [rsp + _INP]
638     add    INP, 64
639     cmp    INP, [rsp + _INP_END]
640     jne    loop0_swap
641
642 done_hash_swap:
643     mov   a, [4*0 + CTX]
644     bswap a
645     mov   [4*0 + CTX],a
646
647     mov   b, [4*1 + CTX]
648     bswap b
649     mov   [4*1 + CTX], b
650
651     mov   c, [4*2 + CTX]
652     bswap c
653     mov   [4*2 + CTX], c
654
655     mov   d, [4*3 + CTX]
656     bswap d
657     mov   [4*3 + CTX], d
658
659     mov   e, [4*4 + CTX]
660     bswap e
661     mov   [4*4 + CTX], e
662
663     mov   f, [4*5 + CTX]
664     bswap f
665     mov   [4*5 + CTX], f
666
667     mov   g, [4*6 + CTX]
668     bswap g
669     mov   [4*6 + CTX], g
670
671     mov   h, [4*7 + CTX]
672     bswap h
673     mov   [4*7 + CTX], h
674
675
676 %ifndef LINUX
677     movdqa    xmm6,[rsp + _XMM_SAVE + 0*16]
678     movdqa    xmm7,[rsp + _XMM_SAVE + 1*16]
679     movdqa    xmm8,[rsp + _XMM_SAVE + 2*16]
680     movdqa    xmm9,[rsp + _XMM_SAVE + 3*16]
681     movdqa    xmm10,[rsp + _XMM_SAVE + 4*16]
682     movdqa    xmm11,[rsp + _XMM_SAVE + 5*16]
683     movdqa    xmm12,[rsp + _XMM_SAVE + 6*16]
684 %endif
685
686     add    rsp, STACK_SIZE
687
688     pop    r15
689     pop    r14
690     pop    r13
691     pop    rbp
692 %ifndef LINUX
693     pop    rdi
694     pop    rsi
695 %endif
696     pop    rbx
697
698     ret
699
700 section .data
701 align 64
702 K256:
703     dd    0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5
704     dd    0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5
705     dd    0xd807aa98,0x12835b01,0x243185be,0x550c7dc3
706     dd    0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174
707     dd    0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc
708     dd    0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da
709     dd    0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7
710     dd    0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967
711     dd    0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13
712     dd    0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85
713     dd    0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3
714     dd    0xd192e819,0xd6990624,0xf40e3585,0x106aa070
715     dd    0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5
716     dd    0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3
717     dd    0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208
718     dd    0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2
719
720 PSHUFFLE_BYTE_FLIP_MASK: ddq 0x0c0d0e0f08090a0b0405060700010203
721
722 ; shuffle xBxA -> 00BA
723 _SHUF_00BA:              ddq 0xFFFFFFFFFFFFFFFF0b0a090803020100
724
725 ; shuffle xDxC -> DC00
726 _SHUF_DC00:              ddq 0x0b0a090803020100FFFFFFFFFFFFFFFF