f26c515e78c33a4950c29acd00f6b7fbdcde3053
[openssl.git] / crypto / rc4 / asm / rc4-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 # February 2009
11 #
12 # Performance is 2x of gcc 3.4.6 on z10. Coding "secret" is to
13 # "cluster" Address Generation Interlocks, so that one pipeline stall
14 # resolves several dependencies.
15
16 while (($output=shift) && ($output!~/^\w[\w\-]*\.\w+$/)) {}
17 open STDOUT,">$output";
18
19 $rp="%r14";
20 $sp="%r15";
21 $code=<<___;
22 .text
23
24 ___
25
26 # void RC4(RC4_KEY *key,size_t len,const void *inp,void *out)
27 {
28 $acc="%r0";
29 $cnt="%r1";
30 $key="%r2";
31 $len="%r3";
32 $inp="%r4";
33 $out="%r5";
34
35 @XX=("%r6","%r7");
36 @TX=("%r8","%r9");
37 $YY="%r10";
38 $TY="%r11";
39
40 $code.=<<___;
41 .globl  RC4
42 .type   RC4,\@function
43 .align  64
44 RC4:
45         stmg    %r6,%r11,48($sp)
46         llgc    $XX[0],0($key)
47         llgc    $YY,1($key)
48         la      $XX[0],1($XX[0])
49         nill    $XX[0],0xff
50         srlg    $cnt,$len,3
51         ltgr    $cnt,$cnt
52         llgc    $TX[0],2($XX[0],$key)
53         jz      .Lshort
54         j       .Loop8
55
56 .align  64
57 .Loop8:
58 ___
59 for ($i=0;$i<8;$i++) {
60 $code.=<<___;
61         la      $YY,0($YY,$TX[0])       # $i
62         nill    $YY,255
63         la      $XX[1],1($XX[0])
64         nill    $XX[1],255
65 ___
66 $code.=<<___ if ($i==1);
67         llgc    $acc,2($TY,$key)
68 ___
69 $code.=<<___ if ($i>1);
70         sllg    $acc,$acc,8
71         ic      $acc,2($TY,$key)
72 ___
73 $code.=<<___;
74         llgc    $TY,2($YY,$key)
75         stc     $TX[0],2($YY,$key)
76         llgc    $TX[1],2($XX[1],$key)
77         stc     $TY,2($XX[0],$key)
78         cr      $XX[1],$YY
79         jne     .Lcmov$i
80         la      $TX[1],0($TX[0])
81 .Lcmov$i:
82         la      $TY,0($TY,$TX[0])
83         nill    $TY,255
84 ___
85 push(@TX,shift(@TX)); push(@XX,shift(@XX));     # "rotate" registers
86 }
87
88 $code.=<<___;
89         lg      $TX[1],0($inp)
90         sllg    $acc,$acc,8
91         la      $inp,8($inp)
92         ic      $acc,2($TY,$key)
93         xgr     $acc,$TX[1]
94         stg     $acc,0($out)
95         la      $out,8($out)
96         brct    $cnt,.Loop8
97
98 .Lshort:
99         lghi    $acc,7
100         ngr     $len,$acc
101         jz      .Lexit
102         j       .Loop1
103
104 .align  16
105 .Loop1:
106         la      $YY,0($YY,$TX[0])
107         nill    $YY,255
108         llgc    $TY,2($YY,$key)
109         stc     $TX[0],2($YY,$key)
110         stc     $TY,2($XX[0],$key)
111         ar      $TY,$TX[0]
112         ahi     $XX[0],1
113         nill    $TY,255
114         nill    $XX[0],255
115         llgc    $acc,0($inp)
116         la      $inp,1($inp)
117         llgc    $TY,2($TY,$key)
118         llgc    $TX[0],2($XX[0],$key)
119         xr      $acc,$TY
120         stc     $acc,0($out)
121         la      $out,1($out)
122         brct    $len,.Loop1
123
124 .Lexit:
125         ahi     $XX[0],-1
126         stc     $XX[0],0($key)
127         stc     $YY,1($key)
128         lmg     %r6,%r11,48($sp)
129         br      $rp
130 .size   RC4,.-RC4
131 .string "RC4 for s390x, CRYPTOGAMS by <appro\@openssl.org>"
132
133 ___
134 }
135
136 # void RC4_set_key(RC4_KEY *key,unsigned int len,const void *inp)
137 {
138 $cnt="%r0";
139 $idx="%r1";
140 $key="%r2";
141 $len="%r3";
142 $inp="%r4";
143 $acc="%r5";
144 $dat="%r6";
145 $ikey="%r7";
146 $iinp="%r8";
147
148 $code.=<<___;
149 .globl  RC4_set_key
150 .type   RC4_set_key,\@function
151 .align  64
152 RC4_set_key:
153         stmg    %r6,%r8,48($sp)
154         lhi     $cnt,256
155         la      $idx,0(%r0)
156         sth     $idx,0($key)
157 .align  4
158 .L1stloop:
159         stc     $idx,2($idx,$key)
160         la      $idx,1($idx)
161         brct    $cnt,.L1stloop
162
163         lghi    $ikey,-256
164         lr      $cnt,$len
165         la      $iinp,0(%r0)
166         la      $idx,0(%r0)
167 .align  16
168 .L2ndloop:
169         llgc    $acc,2+256($ikey,$key)
170         llgc    $dat,0($iinp,$inp)
171         la      $idx,0($idx,$acc)
172         la      $ikey,1($ikey)
173         la      $idx,0($idx,$dat)
174         nill    $idx,255
175         la      $iinp,1($iinp)
176         tml     $ikey,255
177         llgc    $dat,2($idx,$key)
178         stc     $dat,2+256-1($ikey,$key)
179         stc     $acc,2($idx,$key)
180         jz      .Ldone
181         brct    $cnt,.L2ndloop
182         lr      $cnt,$len
183         la      $iinp,0(%r0)
184         j       .L2ndloop
185 .Ldone:
186         lmg     %r6,%r8,48($sp)
187         br      $rp
188 .size   RC4_set_key,.-RC4_set_key
189
190 ___
191 }
192
193 # const char *RC4_options()
194 $code.=<<___;
195 .globl  RC4_options
196 .type   RC4_options,\@function
197 .align  16
198 RC4_options:
199         larl    %r2,.Loptions
200         br      %r14
201 .size   RC4_options,.-RC4_options
202 .section        .rodata
203 .Loptions:
204 .align  8
205 .string "rc4(8x,char)"
206 ___
207
208 print $code;
209 close STDOUT;   # force flush