Minor optimization for sha1-armv4 module.
[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 ___
162 $code.=<<___ if ($i<76);
163         mov     $xi,`4*($j%16)`(%rsp)
164 ___
165 $code.=<<___ if ($i==79);
166         lea     $K($xi,$e),$f
167         mov     $c,$t0
168         mov     $a,$e
169         xor     $b,$t0
170         rol     \$5,$e
171         xor     $d,$t0
172         add     $e,$f
173         rol     \$30,$b
174         add     $t0,$f
175 ___
176 }
177
178 sub BODY_40_59 {
179 my ($i,$a,$b,$c,$d,$e,$f)=@_;
180 my $j=$i+1;
181 $code.=<<___;
182         lea     0x8f1bbcdc($xi,$e),$f
183         mov     `4*($j%16)`(%rsp),$xi
184         mov     $b,$t0
185         mov     $b,$t1
186         xor     `4*(($j+2)%16)`(%rsp),$xi
187         mov     $a,$e
188         and     $c,$t0
189         xor     `4*(($j+8)%16)`(%rsp),$xi
190         or      $c,$t1
191         rol     \$5,$e
192         xor     `4*(($j+13)%16)`(%rsp),$xi
193         and     $d,$t1
194         add     $e,$f
195         rol     \$1,$xi
196         or      $t1,$t0
197         rol     \$30,$b
198         mov     $xi,`4*($j%16)`(%rsp)
199         add     $t0,$f
200 ___
201 }
202
203 $code=".text\n";
204
205 &PROLOGUE("sha1_block_data_order");
206 $code.=".align  4\n.Lloop:\n";
207 for($i=0;$i<20;$i++)    { &BODY_00_19($i,@V); unshift(@V,pop(@V)); }
208 for(;$i<40;$i++)        { &BODY_20_39($i,@V); unshift(@V,pop(@V)); }
209 for(;$i<60;$i++)        { &BODY_40_59($i,@V); unshift(@V,pop(@V)); }
210 for(;$i<80;$i++)        { &BODY_20_39($i,@V); unshift(@V,pop(@V)); }
211 $code.=<<___;
212         add     0($ctx),$E
213         add     4($ctx),$T
214         add     8($ctx),$A
215         add     12($ctx),$B
216         add     16($ctx),$C
217         mov     $E,0($ctx)
218         mov     $T,4($ctx)
219         mov     $A,8($ctx)
220         mov     $B,12($ctx)
221         mov     $C,16($ctx)
222
223         xchg    $E,$A   # mov   $E,$A
224         xchg    $T,$B   # mov   $T,$B
225         xchg    $E,$C   # mov   $A,$C
226         xchg    $T,$D   # mov   $B,$D
227                         # mov   $C,$E
228         lea     `16*4`($inp),$inp
229         sub     \$1,$num
230         jnz     .Lloop
231 ___
232 &EPILOGUE("sha1_block_data_order");
233 $code.=<<___;
234 .asciz  "SHA1 block transform for x86_64, CRYPTOGAMS by <appro\@openssl.org>"
235 ___
236
237 ####################################################################
238
239 $code =~ s/\`([^\`]*)\`/eval $1/gem;
240 print $code;
241 close STDOUT;