003ba7647e4a922b70580167a9b06dc966ad440e
[openssl.git] / crypto / sha / asm / sha1-s390x.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 s390x.
11
12 # April 2007.
13 #
14 # Performance is >30% better than gcc 3.3 generated code. But the real
15 # twist is that SHA1 hardware support is detected and utilized. In
16 # which case performance can reach further >4.5x for larger chunks.
17
18 # January 2009.
19 #
20 # Optimize Xupdate for amount of memory references and reschedule
21 # instructions to favour dual-issue z10 pipeline. On z10 hardware is
22 # "only" ~2.3x faster than software.
23
24 # November 2010.
25 #
26 # Adapt for -m31 build. If kernel supports what's called "highgprs"
27 # feature on Linux [see /proc/cpuinfo], it's possible to use 64-bit
28 # instructions and achieve "64-bit" performance even in 31-bit legacy
29 # application context. The feature is not specific to any particular
30 # processor, as long as it's "z-CPU". Latter implies that the code
31 # remains z/Architecture specific. On z990 it was measured to perform
32 # 23% better than code generated by gcc 4.3.
33
34 $kimdfunc=1;    # magic function code for kimd instruction
35
36 $flavour = shift;
37
38 if ($flavour =~ /3[12]/) {
39         $SIZE_T=4;
40         $g="";
41 } else {
42         $SIZE_T=8;
43         $g="g";
44 }
45
46 while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {}
47 open STDOUT,">$output";
48
49 $K_00_39="%r0"; $K=$K_00_39;
50 $K_40_79="%r1";
51 $ctx="%r2";     $prefetch="%r2";
52 $inp="%r3";
53 $len="%r4";
54
55 $A="%r5";
56 $B="%r6";
57 $C="%r7";
58 $D="%r8";
59 $E="%r9";       @V=($A,$B,$C,$D,$E);
60 $t0="%r10";
61 $t1="%r11";
62 @X=("%r12","%r13","%r14");
63 $sp="%r15";
64
65 $stdframe=16*$SIZE_T+4*8;
66 $frame=$stdframe+16*4;
67
68 sub Xupdate {
69 my $i=shift;
70
71 $code.=<<___ if ($i==15);
72         lg      $prefetch,$stdframe($sp)        ### Xupdate(16) warm-up
73         lr      $X[0],$X[2]
74 ___
75 return if ($i&1);       # Xupdate is vectorized and executed every 2nd cycle
76 $code.=<<___ if ($i<16);
77         lg      $X[0],`$i*4`($inp)      ### Xload($i)
78         rllg    $X[1],$X[0],32
79 ___
80 $code.=<<___ if ($i>=16);
81         xgr     $X[0],$prefetch         ### Xupdate($i)
82         lg      $prefetch,`$stdframe+4*(($i+2)%16)`($sp)
83         xg      $X[0],`$stdframe+4*(($i+8)%16)`($sp)
84         xgr     $X[0],$prefetch
85         rll     $X[0],$X[0],1
86         rllg    $X[1],$X[0],32
87         rll     $X[1],$X[1],1
88         rllg    $X[0],$X[1],32
89         lr      $X[2],$X[1]             # feedback
90 ___
91 $code.=<<___ if ($i<=70);
92         stg     $X[0],`$stdframe+4*($i%16)`($sp)
93 ___
94 unshift(@X,pop(@X));
95 }
96
97 sub BODY_00_19 {
98 my ($i,$a,$b,$c,$d,$e)=@_;
99 my $xi=$X[1];
100
101         &Xupdate($i);
102 $code.=<<___;
103         alr     $e,$K           ### $i
104         rll     $t1,$a,5
105         lr      $t0,$d
106         xr      $t0,$c
107         alr     $e,$t1
108         nr      $t0,$b
109         alr     $e,$xi
110         xr      $t0,$d
111         rll     $b,$b,30
112         alr     $e,$t0
113 ___
114 }
115
116 sub BODY_20_39 {
117 my ($i,$a,$b,$c,$d,$e)=@_;
118 my $xi=$X[1];
119
120         &Xupdate($i);
121 $code.=<<___;
122         alr     $e,$K           ### $i
123         rll     $t1,$a,5
124         lr      $t0,$b
125         alr     $e,$t1
126         xr      $t0,$c
127         alr     $e,$xi
128         xr      $t0,$d
129         rll     $b,$b,30
130         alr     $e,$t0
131 ___
132 }
133
134 sub BODY_40_59 {
135 my ($i,$a,$b,$c,$d,$e)=@_;
136 my $xi=$X[1];
137
138         &Xupdate($i);
139 $code.=<<___;
140         alr     $e,$K           ### $i
141         rll     $t1,$a,5
142         lr      $t0,$b
143         alr     $e,$t1
144         or      $t0,$c
145         lr      $t1,$b
146         nr      $t0,$d
147         nr      $t1,$c
148         alr     $e,$xi
149         or      $t0,$t1
150         rll     $b,$b,30
151         alr     $e,$t0
152 ___
153 }
154
155 $code.=<<___;
156 .text
157 .align  64
158 .type   Ktable,\@object
159 Ktable: .long   0x5a827999,0x6ed9eba1,0x8f1bbcdc,0xca62c1d6
160         .skip   48      #.long  0,0,0,0,0,0,0,0,0,0,0,0
161 .size   Ktable,.-Ktable
162 .globl  sha1_block_data_order
163 .type   sha1_block_data_order,\@function
164 sha1_block_data_order:
165 ___
166 $code.=<<___ if ($kimdfunc);
167         larl    %r1,OPENSSL_s390xcap_P
168         lg      %r0,0(%r1)
169         tmhl    %r0,0x4000      # check for message-security assist
170         jz      .Lsoftware
171         lg      %r0,16(%r1)     # check kimd capabilities
172         tmhh    %r0,`0x8000>>$kimdfunc`
173         jz      .Lsoftware
174         lghi    %r0,$kimdfunc
175         lgr     %r1,$ctx
176         lgr     %r2,$inp
177         sllg    %r3,$len,6
178         .long   0xb93e0002      # kimd %r0,%r2
179         brc     1,.-4           # pay attention to "partial completion"
180         br      %r14
181 .align  16
182 .Lsoftware:
183 ___
184 $code.=<<___;
185         lghi    %r1,-$frame
186         st${g}  $ctx,`2*$SIZE_T`($sp)
187         stm${g} %r6,%r15,`6*$SIZE_T`($sp)
188         lgr     %r0,$sp
189         la      $sp,0(%r1,$sp)
190         st${g}  %r0,0($sp)
191
192         larl    $t0,Ktable
193         llgf    $A,0($ctx)
194         llgf    $B,4($ctx)
195         llgf    $C,8($ctx)
196         llgf    $D,12($ctx)
197         llgf    $E,16($ctx)
198
199         lg      $K_00_39,0($t0)
200         lg      $K_40_79,8($t0)
201
202 .Lloop:
203         rllg    $K_00_39,$K_00_39,32
204 ___
205 for ($i=0;$i<20;$i++)   { &BODY_00_19($i,@V); unshift(@V,pop(@V)); }
206 $code.=<<___;
207         rllg    $K_00_39,$K_00_39,32
208 ___
209 for (;$i<40;$i++)       { &BODY_20_39($i,@V); unshift(@V,pop(@V)); }
210 $code.=<<___;   $K=$K_40_79;
211         rllg    $K_40_79,$K_40_79,32
212 ___
213 for (;$i<60;$i++)       { &BODY_40_59($i,@V); unshift(@V,pop(@V)); }
214 $code.=<<___;
215         rllg    $K_40_79,$K_40_79,32
216 ___
217 for (;$i<80;$i++)       { &BODY_20_39($i,@V); unshift(@V,pop(@V)); }
218 $code.=<<___;
219
220         l${g}   $ctx,`$frame+2*$SIZE_T`($sp)
221         la      $inp,64($inp)
222         al      $A,0($ctx)
223         al      $B,4($ctx)
224         al      $C,8($ctx)
225         al      $D,12($ctx)
226         al      $E,16($ctx)
227         st      $A,0($ctx)
228         st      $B,4($ctx)
229         st      $C,8($ctx)
230         st      $D,12($ctx)
231         st      $E,16($ctx)
232         brct${g} $len,.Lloop
233
234         lm${g}  %r6,%r15,`$frame+6*$SIZE_T`($sp)
235         br      %r14
236 .size   sha1_block_data_order,.-sha1_block_data_order
237 .string "SHA1 block transform for s390x, CRYPTOGAMS by <appro\@openssl.org>"
238 .comm   OPENSSL_s390xcap_P,80,8
239 ___
240
241 $code =~ s/\`([^\`]*)\`/eval $1/gem;
242
243 print $code;
244 close STDOUT;