~vcs-imports/busybox/trunk

« back to all changes in this revision

Viewing changes to libbb/hash_sha1_x86-64.S.sh

  • Committer: Denys Vlasenko
  • Date: 2023-07-18 14:41:12 UTC
  • Revision ID: git-v1:8f0845cad7bfc46939132b33f9cd0753b261b953
libbb: rename source files, no code changes

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!/bin/sh
 
2
 
 
3
# We don't regenerate it on every "make" invocation - only by hand.
 
4
# The reason is that the changes to generated code are difficult
 
5
# to visualize by looking only at this script, it helps when the commit
 
6
# also contains the diff of the generated file.
 
7
exec >hash_sha1_x86-64.S
 
8
 
 
9
# Based on http://arctic.org/~dean/crypto/sha1.html.
 
10
# ("This SHA1 implementation is public domain.")
 
11
#
 
12
# x86-64 has at least SSE2 vector insns always available.
 
13
# We can use them without any CPUID checks (and without a need
 
14
# for a fallback code if needed insns are not available).
 
15
# This code uses them to calculate W[] ahead of time.
 
16
#
 
17
# Unfortunately, results are passed from vector unit to
 
18
# integer ALUs on the stack. MOVD/Q insns to move them directly
 
19
# from vector to integer registers are slower than store-to-load
 
20
# forwarding in LSU (on Skylake at least).
 
21
#
 
22
# The win against a purely integer code is small on Skylake,
 
23
# only about 7-8%. We offload about 1/3 of our operations to the vector unit.
 
24
# It can do 4 ops at once in one 128-bit register,
 
25
# but we have to use x2 of them because of W[0] complication,
 
26
# SSE2 has no "rotate each word by N bits" insns,
 
27
# moving data to/from vector unit is clunky, and Skylake
 
28
# has four integer ALUs unified with three vector ALUs,
 
29
# which makes pure integer code rather fast, and makes
 
30
# vector ops compete with integer ones.
 
31
#
 
32
# Zen3, with its separate vector ALUs, wins more, about 12%.
 
33
 
 
34
xmmT1="%xmm4"
 
35
xmmT2="%xmm5"
 
36
xmmRCONST="%xmm6"
 
37
xmmALLRCONST="%xmm7"
 
38
T=`printf '\t'`
 
39
 
 
40
# SSE instructions are longer than 4 bytes on average.
 
41
# Intel CPUs (up to Tiger Lake at least) can't decode
 
42
# more than 16 bytes of code in one cycle.
 
43
# By interleaving SSE code and integer code
 
44
# we mostly achieve a situation where 16-byte decode fetch window
 
45
# contains 4 (or more) insns.
 
46
#
 
47
# However. On Skylake, there was no observed difference,
 
48
# but on Zen3, non-interleaved code is ~3% faster
 
49
# (822 Mb/s versus 795 Mb/s hashing speed).
 
50
# Off for now:
 
51
interleave=false
 
52
 
 
53
INTERLEAVE() {
 
54
        $interleave || \
 
55
        {
 
56
                # Generate non-interleaved code
 
57
                # (it should work correctly too)
 
58
                echo "$1"
 
59
                echo "$2"
 
60
                return
 
61
        }
 
62
        (
 
63
        echo "$1" | grep -v '^$' >"$0.temp1"
 
64
        echo "$2" | grep -v '^$' >"$0.temp2"
 
65
        exec 3<"$0.temp1"
 
66
        exec 4<"$0.temp2"
 
67
        IFS=''
 
68
        while :; do
 
69
                line1=''
 
70
                line2=''
 
71
                while :; do
 
72
                        read -r line1 <&3
 
73
                        if test "${line1:0:1}" != "#" && test "${line1:0:2}" != "$T#"; then
 
74
                                break
 
75
                        fi
 
76
                        echo "$line1"
 
77
                done
 
78
                while :; do
 
79
                        read -r line2 <&4
 
80
                        if test "${line2:0:4}" = "${T}lea"; then
 
81
                                # We use 7-8 byte long forms of LEA.
 
82
                                # Do not interleave them with SSE insns
 
83
                                # which are also long.
 
84
                                echo "$line2"
 
85
                                read -r line2 <&4
 
86
                                echo "$line2"
 
87
                                continue
 
88
                        fi
 
89
                        if test "${line2:0:1}" != "#" && test "${line2:0:2}" != "$T#"; then
 
90
                                break
 
91
                        fi
 
92
                        echo "$line2"
 
93
                done
 
94
                test "$line1$line2" || break
 
95
                echo "$line1"
 
96
                echo "$line2"
 
97
        done
 
98
        rm "$0.temp1" "$0.temp2"
 
99
        )
 
100
}
 
101
 
 
102
#       movaps  bswap32_mask(%rip), $xmmT1
 
103
# Load W[] to xmm0..3, byteswapping on the fly.
 
104
# For iterations 0..15, we pass RCONST+W[] in rsi,r8..r14
 
105
# for use in RD1As instead of spilling them to stack.
 
106
# (We use rsi instead of rN because this makes two
 
107
# ADDs in two first RD1As shorter by one byte).
 
108
#       movups  16*0(%rdi), %xmm0
 
109
#       pshufb  $xmmT1, %xmm0           #SSSE3 insn
 
110
#       movaps  %xmm0, $xmmT2
 
111
#       paddd   $xmmRCONST, $xmmT2
 
112
#       movq    $xmmT2, %rsi
 
113
#       #pextrq \$1, $xmmT2, %r8        #SSE4.1 insn
 
114
#       #movhpd $xmmT2, %r8             #can only move to mem, not to reg
 
115
#       shufps  \$0x0e, $xmmT2, $xmmT2  # have to use two-insn sequence
 
116
#       movq    $xmmT2, %r8             # instead
 
117
#       ...
 
118
#       <repeat for xmm1,2,3>
 
119
#       ...
 
120
#-      leal    $RCONST(%r$e,%rsi), %e$e        # e += RCONST + W[n]
 
121
#+      addl    %esi, %e$e                      # e += RCONST + W[n]
 
122
# ^^^^^^^^^^^^^^^^^^^^^^^^
 
123
# The above is -97 bytes of code...
 
124
# ...but pshufb is a SSSE3 insn. Can't use it.
 
125
 
 
126
echo \
 
127
"### Generated by hash_sha1_x86-64.S.sh ###
 
128
 
 
129
#if CONFIG_SHA1_SMALL == 0 && defined(__GNUC__) && defined(__x86_64__)
 
130
#ifdef __linux__
 
131
        .section        .note.GNU-stack, \"\", @progbits
 
132
#endif
 
133
        .section        .text.sha1_process_block64, \"ax\", @progbits
 
134
        .globl  sha1_process_block64
 
135
        .hidden sha1_process_block64
 
136
        .type   sha1_process_block64, @function
 
137
 
 
138
        .balign 8       # allow decoders to fetch at least 5 first insns
 
139
sha1_process_block64:
 
140
        pushq   %rbp    # 1 byte insn
 
141
        pushq   %rbx    # 1 byte insn
 
142
#       pushq   %r15    # 2 byte insn
 
143
        pushq   %r14    # 2 byte insn
 
144
        pushq   %r13    # 2 byte insn
 
145
        pushq   %r12    # 2 byte insn
 
146
        pushq   %rdi    # we need ctx at the end
 
147
 
 
148
#Register and stack use:
 
149
# eax..edx: a..d
 
150
# ebp: e
 
151
# esi,edi,r8..r14: temps
 
152
# r15: unused
 
153
# xmm0..xmm3: W[]
 
154
# xmm4,xmm5: temps
 
155
# xmm6: current round constant
 
156
# xmm7: all round constants
 
157
# -64(%rsp): area for passing RCONST + W[] from vector to integer units
 
158
 
 
159
        movl    80(%rdi), %eax          # a = ctx->hash[0]
 
160
        movl    84(%rdi), %ebx          # b = ctx->hash[1]
 
161
        movl    88(%rdi), %ecx          # c = ctx->hash[2]
 
162
        movl    92(%rdi), %edx          # d = ctx->hash[3]
 
163
        movl    96(%rdi), %ebp          # e = ctx->hash[4]
 
164
 
 
165
        movaps  sha1const(%rip), $xmmALLRCONST
 
166
        pshufd  \$0x00, $xmmALLRCONST, $xmmRCONST
 
167
 
 
168
        # Load W[] to xmm0..3, byteswapping on the fly.
 
169
        #
 
170
        # For iterations 0..15, we pass W[] in rsi,r8..r14
 
171
        # for use in RD1As instead of spilling them to stack.
 
172
        # We lose parallelized addition of RCONST, but LEA
 
173
        # can do two additions at once, so it is probably a wash.
 
174
        # (We use rsi instead of rN because this makes two
 
175
        # LEAs in two first RD1As shorter by one byte).
 
176
        movq    4*0(%rdi), %rsi
 
177
        movq    4*2(%rdi), %r8
 
178
        bswapq  %rsi
 
179
        bswapq  %r8
 
180
        rolq    \$32, %rsi              # rsi = W[1]:W[0]
 
181
        rolq    \$32, %r8               # r8  = W[3]:W[2]
 
182
        movq    %rsi, %xmm0
 
183
        movq    %r8, $xmmT1
 
184
        punpcklqdq $xmmT1, %xmm0        # xmm0 = r8:rsi = (W[0],W[1],W[2],W[3])
 
185
#       movaps  %xmm0, $xmmT1           # add RCONST, spill to stack
 
186
#       paddd   $xmmRCONST, $xmmT1
 
187
#       movups  $xmmT1, -64+16*0(%rsp)
 
188
 
 
189
        movq    4*4(%rdi), %r9
 
190
        movq    4*6(%rdi), %r10
 
191
        bswapq  %r9
 
192
        bswapq  %r10
 
193
        rolq    \$32, %r9               # r9  = W[5]:W[4]
 
194
        rolq    \$32, %r10              # r10 = W[7]:W[6]
 
195
        movq    %r9, %xmm1
 
196
        movq    %r10, $xmmT1
 
197
        punpcklqdq $xmmT1, %xmm1        # xmm1 = r10:r9 = (W[4],W[5],W[6],W[7])
 
198
 
 
199
        movq    4*8(%rdi), %r11
 
200
        movq    4*10(%rdi), %r12
 
201
        bswapq  %r11
 
202
        bswapq  %r12
 
203
        rolq    \$32, %r11              # r11 = W[9]:W[8]
 
204
        rolq    \$32, %r12              # r12 = W[11]:W[10]
 
205
        movq    %r11, %xmm2
 
206
        movq    %r12, $xmmT1
 
207
        punpcklqdq $xmmT1, %xmm2        # xmm2 = r12:r11 = (W[8],W[9],W[10],W[11])
 
208
 
 
209
        movq    4*12(%rdi), %r13
 
210
        movq    4*14(%rdi), %r14
 
211
        bswapq  %r13
 
212
        bswapq  %r14
 
213
        rolq    \$32, %r13              # r13 = W[13]:W[12]
 
214
        rolq    \$32, %r14              # r14 = W[15]:W[14]
 
215
        movq    %r13, %xmm3
 
216
        movq    %r14, $xmmT1
 
217
        punpcklqdq $xmmT1, %xmm3        # xmm3 = r14:r13 = (W[12],W[13],W[14],W[15])
 
218
"
 
219
 
 
220
PREP() {
 
221
local xmmW0=$1
 
222
local xmmW4=$2
 
223
local xmmW8=$3
 
224
local xmmW12=$4
 
225
# the above must be %xmm0..3 in some permutation
 
226
local dstmem=$5
 
227
#W[0] = rol(W[13] ^ W[8]  ^ W[2] ^ W[0], 1);
 
228
#W[1] = rol(W[14] ^ W[9]  ^ W[3] ^ W[1], 1);
 
229
#W[2] = rol(W[15] ^ W[10] ^ W[4] ^ W[2], 1);
 
230
#W[3] = rol(  0   ^ W[11] ^ W[5] ^ W[3], 1);
 
231
#W[3] ^= rol(W[0], 1);
 
232
echo "# PREP $@
 
233
        movaps  $xmmW12, $xmmT1
 
234
        psrldq  \$4, $xmmT1     # rshift by 4 bytes: T1 = ([13],[14],[15],0)
 
235
 
 
236
#       pshufd  \$0x4e, $xmmW0, $xmmT2  # 01001110=2,3,0,1 shuffle, ([2],[3],x,x)
 
237
#       punpcklqdq $xmmW4, $xmmT2       # T2 = W4[0..63]:T2[0..63] = ([2],[3],[4],[5])
 
238
# same result as above, but shorter and faster:
 
239
# pshufd/shufps are subtly different: pshufd takes all dwords from source operand,
 
240
# shufps takes dwords 0,1 from *2nd* operand, and dwords 2,3 from 1st one!
 
241
        movaps  $xmmW0, $xmmT2
 
242
        shufps  \$0x4e, $xmmW4, $xmmT2  # 01001110=(T2.dw[2], T2.dw[3], W4.dw[0], W4.dw[1]) = ([2],[3],[4],[5])
 
243
 
 
244
        xorps   $xmmW8, $xmmW0  # ([8],[9],[10],[11]) ^ ([0],[1],[2],[3])
 
245
        xorps   $xmmT1, $xmmT2  # ([13],[14],[15],0) ^ ([2],[3],[4],[5])
 
246
        xorps   $xmmT2, $xmmW0  # ^
 
247
        # W0 = unrotated (W[0]..W[3]), still needs W[3] fixup
 
248
        movaps  $xmmW0, $xmmT2
 
249
 
 
250
        xorps   $xmmT1, $xmmT1  # rol(W0,1):
 
251
        pcmpgtd $xmmW0, $xmmT1  #  ffffffff for elements <0 (ones with msb bit 1)
 
252
        paddd   $xmmW0, $xmmW0  #  shift left by 1
 
253
        psubd   $xmmT1, $xmmW0  #  add 1 to those who had msb bit 1
 
254
        # W0 = rotated (W[0]..W[3]), still needs W[3] fixup
 
255
 
 
256
        pslldq  \$12, $xmmT2    # lshift by 12 bytes: T2 = (0,0,0,unrotW[0])
 
257
        movaps  $xmmT2, $xmmT1
 
258
        pslld   \$2, $xmmT2
 
259
        psrld   \$30, $xmmT1
 
260
#       xorps   $xmmT1, $xmmT2  # rol((0,0,0,unrotW[0]),2)
 
261
        xorps   $xmmT1, $xmmW0  # same result, but does not depend on/does not modify T2
 
262
 
 
263
        xorps   $xmmT2, $xmmW0  # W0 = rol(W[0]..W[3],1) ^ (0,0,0,rol(unrotW[0],2))
 
264
"
 
265
#       movq    $xmmW0, %r8     # high latency (~6 cycles)
 
266
#       movaps  $xmmW0, $xmmT1
 
267
#       psrldq  \$8, $xmmT1     # rshift by 8 bytes: move upper 64 bits to lower
 
268
#       movq    $xmmT1, %r10    # high latency
 
269
#       movq    %r8, %r9
 
270
#       movq    %r10, %r11
 
271
#       shrq    \$32, %r9
 
272
#       shrq    \$32, %r11
 
273
# ^^^ slower than passing the results on stack (!!!)
 
274
echo "
 
275
        movaps  $xmmW0, $xmmT2
 
276
        paddd   $xmmRCONST, $xmmT2
 
277
        movups  $xmmT2, $dstmem
 
278
"
 
279
}
 
280
 
 
281
# It's possible to interleave integer insns in rounds to mostly eliminate
 
282
# dependency chains, but this likely to only help old Pentium-based
 
283
# CPUs (ones without OOO, which can only simultaneously execute a pair
 
284
# of _adjacent_ insns).
 
285
# Testing on old-ish Silvermont CPU (which has OOO window of only
 
286
# about ~8 insns) shows very small (~1%) speedup.
 
287
 
 
288
RD1A() {
 
289
local a=$1;local b=$2;local c=$3;local d=$4;local e=$5
 
290
local n=$(($6))
 
291
local n0=$(((n+0) & 15))
 
292
local rN=$((7+n0/2))
 
293
echo "
 
294
# $n
 
295
";test $n0 = 0 && echo "
 
296
        leal    $RCONST(%r$e,%rsi), %e$e # e += RCONST + W[n]
 
297
        shrq    \$32, %rsi
 
298
";test $n0 = 1 && echo "
 
299
        leal    $RCONST(%r$e,%rsi), %e$e # e += RCONST + W[n]
 
300
";test $n0 -ge 2 && test $((n0 & 1)) = 0 && echo "
 
301
        leal    $RCONST(%r$e,%r$rN), %e$e # e += RCONST + W[n]
 
302
        shrq    \$32, %r$rN
 
303
";test $n0 -ge 2 && test $((n0 & 1)) = 1 && echo "
 
304
        leal    $RCONST(%r$e,%r$rN), %e$e # e += RCONST + W[n]
 
305
";echo "
 
306
        movl    %e$c, %edi              # c
 
307
        xorl    %e$d, %edi              # ^d
 
308
        andl    %e$b, %edi              # &b
 
309
        xorl    %e$d, %edi              # (((c ^ d) & b) ^ d)
 
310
        addl    %edi, %e$e              # e += (((c ^ d) & b) ^ d)
 
311
        movl    %e$a, %edi              #
 
312
        roll    \$5, %edi               # rotl32(a,5)
 
313
        addl    %edi, %e$e              # e += rotl32(a,5)
 
314
        rorl    \$2, %e$b               # b = rotl32(b,30)
 
315
"
 
316
}
 
317
RD1B() {
 
318
local a=$1;local b=$2;local c=$3;local d=$4;local e=$5
 
319
local n=$(($6))
 
320
local n13=$(((n+13) & 15))
 
321
local n8=$(((n+8) & 15))
 
322
local n2=$(((n+2) & 15))
 
323
local n0=$(((n+0) & 15))
 
324
echo "
 
325
# $n
 
326
        movl    %e$c, %edi              # c
 
327
        xorl    %e$d, %edi              # ^d
 
328
        andl    %e$b, %edi              # &b
 
329
        xorl    %e$d, %edi              # (((c ^ d) & b) ^ d)
 
330
        addl    -64+4*$n0(%rsp), %e$e   # e += RCONST + W[n & 15]
 
331
        addl    %edi, %e$e              # e += (((c ^ d) & b) ^ d)
 
332
        movl    %e$a, %esi              #
 
333
        roll    \$5, %esi               # rotl32(a,5)
 
334
        addl    %esi, %e$e              # e += rotl32(a,5)
 
335
        rorl    \$2, %e$b               # b = rotl32(b,30)
 
336
"
 
337
}
 
338
 
 
339
RD2() {
 
340
local a=$1;local b=$2;local c=$3;local d=$4;local e=$5
 
341
local n=$(($6))
 
342
local n13=$(((n+13) & 15))
 
343
local n8=$(((n+8) & 15))
 
344
local n2=$(((n+2) & 15))
 
345
local n0=$(((n+0) & 15))
 
346
echo "
 
347
# $n
 
348
        movl    %e$c, %edi              # c
 
349
        xorl    %e$d, %edi              # ^d
 
350
        xorl    %e$b, %edi              # ^b
 
351
        addl    -64+4*$n0(%rsp), %e$e   # e += RCONST + W[n & 15]
 
352
        addl    %edi, %e$e              # e += (c ^ d ^ b)
 
353
        movl    %e$a, %esi              #
 
354
        roll    \$5, %esi               # rotl32(a,5)
 
355
        addl    %esi, %e$e              # e += rotl32(a,5)
 
356
        rorl    \$2, %e$b               # b = rotl32(b,30)
 
357
"
 
358
}
 
359
 
 
360
RD3() {
 
361
local a=$1;local b=$2;local c=$3;local d=$4;local e=$5
 
362
local n=$(($6))
 
363
local n13=$(((n+13) & 15))
 
364
local n8=$(((n+8) & 15))
 
365
local n2=$(((n+2) & 15))
 
366
local n0=$(((n+0) & 15))
 
367
echo "
 
368
# $n
 
369
        movl    %e$b, %edi              # di: b
 
370
        movl    %e$b, %esi              # si: b
 
371
        orl     %e$c, %edi              # di: b | c
 
372
        andl    %e$c, %esi              # si: b & c
 
373
        andl    %e$d, %edi              # di: (b | c) & d
 
374
        orl     %esi, %edi              # ((b | c) & d) | (b & c)
 
375
        addl    %edi, %e$e              # += ((b | c) & d) | (b & c)
 
376
        addl    -64+4*$n0(%rsp), %e$e   # e += RCONST + W[n & 15]
 
377
        movl    %e$a, %esi              #
 
378
        roll    \$5, %esi               # rotl32(a,5)
 
379
        addl    %esi, %e$e              # e += rotl32(a,5)
 
380
        rorl    \$2, %e$b               # b = rotl32(b,30)
 
381
"
 
382
}
 
383
 
 
384
{
 
385
# Round 1
 
386
RCONST=0x5A827999
 
387
RD1A ax bx cx dx bp  0; RD1A bp ax bx cx dx  1; RD1A dx bp ax bx cx  2; RD1A cx dx bp ax bx  3;
 
388
RD1A bx cx dx bp ax  4; RD1A ax bx cx dx bp  5; RD1A bp ax bx cx dx  6; RD1A dx bp ax bx cx  7;
 
389
a=`PREP %xmm0 %xmm1 %xmm2 %xmm3 "-64+16*0(%rsp)"`
 
390
b=`RD1A cx dx bp ax bx  8; RD1A bx cx dx bp ax  9; RD1A ax bx cx dx bp 10; RD1A bp ax bx cx dx 11;`
 
391
INTERLEAVE "$a" "$b"
 
392
a=`echo "       pshufd  \\$0x55, $xmmALLRCONST, $xmmRCONST"
 
393
   PREP %xmm1 %xmm2 %xmm3 %xmm0 "-64+16*1(%rsp)"`
 
394
b=`RD1A dx bp ax bx cx 12; RD1A cx dx bp ax bx 13; RD1A bx cx dx bp ax 14; RD1A ax bx cx dx bp 15;`
 
395
INTERLEAVE "$a" "$b"
 
396
a=`PREP %xmm2 %xmm3 %xmm0 %xmm1 "-64+16*2(%rsp)"`
 
397
b=`RD1B bp ax bx cx dx 16; RD1B dx bp ax bx cx 17; RD1B cx dx bp ax bx 18; RD1B bx cx dx bp ax 19;`
 
398
INTERLEAVE "$a" "$b"
 
399
 
 
400
# Round 2
 
401
RCONST=0x6ED9EBA1
 
402
a=`PREP %xmm3 %xmm0 %xmm1 %xmm2 "-64+16*3(%rsp)"`
 
403
b=`RD2 ax bx cx dx bp 20; RD2 bp ax bx cx dx 21; RD2 dx bp ax bx cx 22; RD2 cx dx bp ax bx 23;`
 
404
INTERLEAVE "$a" "$b"
 
405
a=`PREP %xmm0 %xmm1 %xmm2 %xmm3 "-64+16*0(%rsp)"`
 
406
b=`RD2 bx cx dx bp ax 24; RD2 ax bx cx dx bp 25; RD2 bp ax bx cx dx 26; RD2 dx bp ax bx cx 27;`
 
407
INTERLEAVE "$a" "$b"
 
408
a=`PREP %xmm1 %xmm2 %xmm3 %xmm0 "-64+16*1(%rsp)"`
 
409
b=`RD2 cx dx bp ax bx 28; RD2 bx cx dx bp ax 29; RD2 ax bx cx dx bp 30; RD2 bp ax bx cx dx 31;`
 
410
INTERLEAVE "$a" "$b"
 
411
a=`echo "       pshufd  \\$0xaa, $xmmALLRCONST, $xmmRCONST"
 
412
   PREP %xmm2 %xmm3 %xmm0 %xmm1 "-64+16*2(%rsp)"`
 
413
b=`RD2 dx bp ax bx cx 32; RD2 cx dx bp ax bx 33; RD2 bx cx dx bp ax 34; RD2 ax bx cx dx bp 35;`
 
414
INTERLEAVE "$a" "$b"
 
415
a=`PREP %xmm3 %xmm0 %xmm1 %xmm2 "-64+16*3(%rsp)"`
 
416
b=`RD2 bp ax bx cx dx 36; RD2 dx bp ax bx cx 37; RD2 cx dx bp ax bx 38; RD2 bx cx dx bp ax 39;`
 
417
INTERLEAVE "$a" "$b"
 
418
 
 
419
# Round 3
 
420
RCONST=0x8F1BBCDC
 
421
a=`PREP %xmm0 %xmm1 %xmm2 %xmm3 "-64+16*0(%rsp)"`
 
422
b=`RD3 ax bx cx dx bp 40; RD3 bp ax bx cx dx 41; RD3 dx bp ax bx cx 42; RD3 cx dx bp ax bx 43;`
 
423
INTERLEAVE "$a" "$b"
 
424
a=`PREP %xmm1 %xmm2 %xmm3 %xmm0 "-64+16*1(%rsp)"`
 
425
b=`RD3 bx cx dx bp ax 44; RD3 ax bx cx dx bp 45; RD3 bp ax bx cx dx 46; RD3 dx bp ax bx cx 47;`
 
426
INTERLEAVE "$a" "$b"
 
427
a=`PREP %xmm2 %xmm3 %xmm0 %xmm1 "-64+16*2(%rsp)"`
 
428
b=`RD3 cx dx bp ax bx 48; RD3 bx cx dx bp ax 49; RD3 ax bx cx dx bp 50; RD3 bp ax bx cx dx 51;`
 
429
INTERLEAVE "$a" "$b"
 
430
a=`echo "       pshufd  \\$0xff, $xmmALLRCONST, $xmmRCONST"
 
431
   PREP %xmm3 %xmm0 %xmm1 %xmm2 "-64+16*3(%rsp)"`
 
432
b=`RD3 dx bp ax bx cx 52; RD3 cx dx bp ax bx 53; RD3 bx cx dx bp ax 54; RD3 ax bx cx dx bp 55;`
 
433
INTERLEAVE "$a" "$b"
 
434
a=`PREP %xmm0 %xmm1 %xmm2 %xmm3 "-64+16*0(%rsp)"`
 
435
b=`RD3 bp ax bx cx dx 56; RD3 dx bp ax bx cx 57; RD3 cx dx bp ax bx 58; RD3 bx cx dx bp ax 59;`
 
436
INTERLEAVE "$a" "$b"
 
437
 
 
438
# Round 4 has the same logic as round 2, only n and RCONST are different
 
439
RCONST=0xCA62C1D6
 
440
a=`PREP %xmm1 %xmm2 %xmm3 %xmm0 "-64+16*1(%rsp)"`
 
441
b=`RD2 ax bx cx dx bp 60; RD2 bp ax bx cx dx 61; RD2 dx bp ax bx cx 62; RD2 cx dx bp ax bx 63;`
 
442
INTERLEAVE "$a" "$b"
 
443
a=`PREP %xmm2 %xmm3 %xmm0 %xmm1 "-64+16*2(%rsp)"`
 
444
b=`RD2 bx cx dx bp ax 64; RD2 ax bx cx dx bp 65; RD2 bp ax bx cx dx 66; RD2 dx bp ax bx cx 67;`
 
445
INTERLEAVE "$a" "$b"
 
446
a=`PREP %xmm3 %xmm0 %xmm1 %xmm2 "-64+16*3(%rsp)"`
 
447
b=`RD2 cx dx bp ax bx 68; RD2 bx cx dx bp ax 69; RD2 ax bx cx dx bp 70; RD2 bp ax bx cx dx 71;`
 
448
INTERLEAVE "$a" "$b"
 
449
RD2 dx bp ax bx cx 72; RD2 cx dx bp ax bx 73; RD2 bx cx dx bp ax 74; RD2 ax bx cx dx bp 75;
 
450
RD2 bp ax bx cx dx 76; RD2 dx bp ax bx cx 77; RD2 cx dx bp ax bx 78; RD2 bx cx dx bp ax 79;
 
451
} | grep -v '^$'
 
452
 
 
453
echo "
 
454
        popq    %rdi            #
 
455
        popq    %r12            #
 
456
        addl    %eax, 80(%rdi)  # ctx->hash[0] += a
 
457
        popq    %r13            #
 
458
        addl    %ebx, 84(%rdi)  # ctx->hash[1] += b
 
459
        popq    %r14            #
 
460
        addl    %ecx, 88(%rdi)  # ctx->hash[2] += c
 
461
#       popq    %r15            #
 
462
        addl    %edx, 92(%rdi)  # ctx->hash[3] += d
 
463
        popq    %rbx            #
 
464
        addl    %ebp, 96(%rdi)  # ctx->hash[4] += e
 
465
        popq    %rbp            #
 
466
 
 
467
        ret
 
468
        .size   sha1_process_block64, .-sha1_process_block64
 
469
 
 
470
        .section        .rodata.cst16.sha1const, \"aM\", @progbits, 16
 
471
        .balign 16
 
472
sha1const:
 
473
        .long   0x5A827999
 
474
        .long   0x6ED9EBA1
 
475
        .long   0x8F1BBCDC
 
476
        .long   0xCA62C1D6
 
477
 
 
478
#endif"