Further synchronizations with md32_common.h update.
[openssl.git] / crypto / sha / asm / sha1-x86_64.pl
1 #!/usr/bin/env perl
2 #
3 # ====================================================================
4 # Written by Andy Polyakov <appro@fy.chalmers.se> for the OpenSSL
5 # project. The module is, however, dual licensed under OpenSSL and
6 # CRYPTOGAMS licenses depending on where you obtain it. For further
7 # details see http://www.openssl.org/~appro/cryptogams/.
8 # ====================================================================
9 #
10 # sha1_block procedure for x86_64.
11 #
12 # It was brought to my attention that on EM64T compiler-generated code
13 # was far behind 32-bit assembler implementation. This is unlike on
14 # Opteron where compiler-generated code was only 15% behind 32-bit
15 # assembler, which originally made it hard to motivate the effort.
16 # There was suggestion to mechanically translate 32-bit code, but I
17 # dismissed it, reasoning that x86_64 offers enough register bank
18 # capacity to fully utilize SHA-1 parallelism. Therefore this fresh
19 # implementation:-) However! While 64-bit code does performs better
20 # on Opteron, I failed to beat 32-bit assembler on EM64T core. Well,
21 # x86_64 does offer larger *addressable* bank, but out-of-order core
22 # reaches for even more registers through dynamic aliasing, and EM64T
23 # core must have managed to run-time optimize even 32-bit code just as
24 # good as 64-bit one. Performance improvement is summarized in the
25 # following table:
26 #
27 #               gcc 3.4         32-bit asm      cycles/byte
28 # Opteron       +45%            +20%            6.8
29 # Xeon          +65%            +0%             9.9
30
31 $output=shift;
32
33 $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
34 ( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or
35 ( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or
36 die "can't locate x86_64-xlate.pl";
37
38 open STDOUT,"| $^X $xlate $output";
39
40 $ctx="%rdi";    # 1st arg
41 $inp="%rsi";    # 2nd arg
42 $num="%rdx";    # 3rd arg
43
44 # reassign arguments in order to produce more compact code
45 $ctx="%r8";
46 $inp="%r9";
47 $num="%r10";
48
49 $xi="%eax";
50 $t0="%ebx";
51 $t1="%ecx";
52 $A="%edx";
53 $B="%esi";
54 $C="%edi";
55 $D="%ebp";
56 $E="%r11d";
57 $T="%r12d";
58
59 @V=($A,$B,$C,$D,$E,$T);
60
61 sub PROLOGUE {
62 my $func=shift;
63 $code.=<<___;
64 .globl  $func
65 .type   $func,\@function,3
66 .align  16
67 $func:
68         push    %rbx
69         push    %rbp
70         push    %r12
71         mov     %rsp,%rax
72         mov     %rdi,$ctx       # reassigned argument
73         sub     \$`8+16*4`,%rsp
74         mov     %rsi,$inp       # reassigned argument
75         and     \$-64,%rsp
76         mov     %rdx,$num       # reassigned argument
77         mov     %rax,`16*4`(%rsp)
78
79         mov     0($ctx),$A
80         mov     4($ctx),$B
81         mov     8($ctx),$C
82         mov     12($ctx),$D
83         mov     16($ctx),$E
84 ___
85 }
86
87 sub EPILOGUE {
88 my $func=shift;
89 $code.=<<___;
90         mov     `16*4`(%rsp),%rsp
91         pop     %r12
92         pop     %rbp
93         pop     %rbx
94         ret
95 .size   $func,.-$func
96 ___
97 }
98
99 sub BODY_00_19 {
100 my ($i,$a,$b,$c,$d,$e,$f,$host)=@_;
101 my $j=$i+1;
102 $code.=<<___ if ($i==0);
103         mov     `4*$i`($inp),$xi        
104         `"bswap $xi"    if(!defined($host))`
105         mov     $xi,`4*$i`(%rsp)
106 ___
107 $code.=<<___ if ($i<15);
108         lea     0x5a827999($xi,$e),$f
109         mov     $c,$t0
110         mov     `4*$j`($inp),$xi
111         mov     $a,$e
112         xor     $d,$t0
113         `"bswap $xi"    if(!defined($host))`    
114         rol     \$5,$e
115         and     $b,$t0
116         mov     $xi,`4*$j`(%rsp)
117         add     $e,$f
118         xor     $d,$t0
119         rol     \$30,$b
120         add     $t0,$f
121 ___
122 $code.=<<___ if ($i>=15);
123         lea     0x5a827999($xi,$e),$f
124         mov     `4*($j%16)`(%rsp),$xi
125         mov     $c,$t0
126         mov     $a,$e
127         xor     `4*(($j+2)%16)`(%rsp),$xi
128         xor     $d,$t0
129         rol     \$5,$e
130         xor     `4*(($j+8)%16)`(%rsp),$xi
131         and     $b,$t0
132         add     $e,$f
133         xor     `4*(($j+13)%16)`(%rsp),$xi
134         xor     $d,$t0
135         rol     \$30,$b
136         add     $t0,$f
137         rol     \$1,$xi
138         mov     $xi,`4*($j%16)`(%rsp)
139 ___
140 }
141
142 sub BODY_20_39 {
143 my ($i,$a,$b,$c,$d,$e,$f)=@_;
144 my $j=$i+1;
145 my $K=($i<40)?0x6ed9eba1:0xca62c1d6;
146 $code.=<<___ if ($i<79);
147         lea     $K($xi,$e),$f
148         mov     `4*($j%16)`(%rsp),$xi
149         mov     $c,$t0
150         mov     $a,$e
151         xor     `4*(($j+2)%16)`(%rsp),$xi
152         xor     $b,$t0
153         rol     \$5,$e
154         xor     `4*(($j+8)%16)`(%rsp),$xi
155         xor     $d,$t0
156         add     $e,$f
157         xor     `4*(($j+13)%16)`(%rsp),$xi
158         rol     \$30,$b
159         add     $t0,$f
160         rol     \$1,$xi
161         mov     $xi,`4*($j%16)`(%rsp)
162 ___
163 $code.=<<___ if ($i==79);
164         lea     $K($xi,$e),$f
165         mov     $c,$t0
166         mov     $a,$e
167         xor     $b,$t0
168         rol     \$5,$e
169         xor     $d,$t0
170         add     $e,$f
171         rol     \$30,$b
172         add     $t0,$f
173 ___
174 }
175
176 sub BODY_40_59 {
177 my ($i,$a,$b,$c,$d,$e,$f)=@_;
178 my $j=$i+1;
179 $code.=<<___;
180         lea     0x8f1bbcdc($xi,$e),$f
181         mov     `4*($j%16)`(%rsp),$xi
182         mov     $b,$t0
183         mov     $b,$t1
184         xor     `4*(($j+2)%16)`(%rsp),$xi
185         mov     $a,$e
186         and     $c,$t0
187         xor     `4*(($j+8)%16)`(%rsp),$xi
188         or      $c,$t1
189         rol     \$5,$e
190         xor     `4*(($j+13)%16)`(%rsp),$xi
191         and     $d,$t1
192         add     $e,$f
193         rol     \$1,$xi
194         or      $t1,$t0
195         rol     \$30,$b
196         mov     $xi,`4*($j%16)`(%rsp)
197         add     $t0,$f
198 ___
199 }
200
201 $code=".text\n";
202
203 &PROLOGUE("sha1_block_asm_data_order");
204 $code.=".align  4\n.Lloop:\n";
205 for($i=0;$i<20;$i++)    { &BODY_00_19($i,@V); unshift(@V,pop(@V)); }
206 for(;$i<40;$i++)        { &BODY_20_39($i,@V); unshift(@V,pop(@V)); }
207 for(;$i<60;$i++)        { &BODY_40_59($i,@V); unshift(@V,pop(@V)); }
208 for(;$i<80;$i++)        { &BODY_20_39($i,@V); unshift(@V,pop(@V)); }
209 $code.=<<___;
210         add     0($ctx),$E
211         add     4($ctx),$T
212         add     8($ctx),$A
213         add     12($ctx),$B
214         add     16($ctx),$C
215         mov     $E,0($ctx)
216         mov     $T,4($ctx)
217         mov     $A,8($ctx)
218         mov     $B,12($ctx)
219         mov     $C,16($ctx)
220
221         xchg    $E,$A   # mov   $E,$A
222         xchg    $T,$B   # mov   $T,$B
223         xchg    $E,$C   # mov   $A,$C
224         xchg    $T,$D   # mov   $B,$D
225                         # mov   $C,$E
226         lea     `16*4`($inp),$inp
227         sub     \$1,$num
228         jnz     .Lloop
229 ___
230 &EPILOGUE("sha1_block_asm_data_order");
231 $code.=<<___;
232 .asciz  "SHA1 block transform for x86_64, CRYPTOGAMS by <appro\@openssl.org>"
233 ___
234
235 ####################################################################
236
237 $code =~ s/\`([^\`]*)\`/eval $1/gem;
238 print $code;
239 close STDOUT;