b69809a97e81067b2bdbe839ede100662936d6b3
[openssl.git] / crypto / bn / asm / ppc-mont.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 # April 2006
11
12 # "Teaser" Montgomery multiplication module for PowerPC. It's possible
13 # to gain a bit more by modulo-scheduling outer loop, then dedicated
14 # squaring procedure should give further 20% and code can be adapted
15 # for 32-bit application running on 64-bit CPU. As for the latter.
16 # It won't be able to achieve "native" 64-bit performance, because in
17 # 32-bit application context every addc instruction will have to be
18 # expanded as addc, twice right shift by 32 and finally adde, etc.
19 # So far RSA *sign* performance improvement over pre-bn_mul_mont asm
20 # for 64-bit application running on PPC970/G5 is:
21 #
22 # 512-bit       +65%    
23 # 1024-bit      +35%
24 # 2048-bit      +18%
25 # 4096-bit      +4%
26
27 $output = shift;
28
29 if ($output =~ /32\-mont\.s/) {
30         $BITS=  32;
31         $BNSZ=  $BITS/8;
32         $SIZE_T=4;
33         $RZONE= 224;
34         $FRAME= $SIZE_T*16;
35
36         $LD=    "lwz";          # load
37         $LDU=   "lwzu";         # load and update
38         $LDX=   "lwzx";         # load indexed
39         $ST=    "stw";          # store
40         $STU=   "stwu";         # store and update
41         $STX=   "stwx";         # store indexed
42         $STUX=  "stwux";        # store indexed and update
43         $UMULL= "mullw";        # unsigned multiply low
44         $UMULH= "mulhwu";       # unsigned multiply high
45         $UCMP=  "cmplw";        # unsigned compare
46         $SHRI=  "srwi";         # unsigned shift right by immediate     
47         $PUSH=  $ST;
48         $POP=   $LD;
49 } elsif ($output =~ /64\-mont\.s/) {
50         $BITS=  64;
51         $BNSZ=  $BITS/8;
52         $SIZE_T=8;
53         $RZONE= 288;
54         $FRAME= $SIZE_T*16;
55
56         # same as above, but 64-bit mnemonics...
57         $LD=    "ld";           # load
58         $LDU=   "ldu";          # load and update
59         $LDX=   "ldx";          # load indexed
60         $ST=    "std";          # store
61         $STU=   "stdu";         # store and update
62         $STX=   "stdx";         # store indexed
63         $STUX=  "stdux";        # store indexed and update
64         $UMULL= "mulld";        # unsigned multiply low
65         $UMULH= "mulhdu";       # unsigned multiply high
66         $UCMP=  "cmpld";        # unsigned compare
67         $SHRI=  "srdi";         # unsigned shift right by immediate     
68         $PUSH=  $ST;
69         $POP=   $LD;
70 } else { die "nonsense $output"; }
71
72 ( defined shift || open STDOUT,"| $^X ../perlasm/ppc-xlate.pl $output" ) ||
73         die "can't call ../perlasm/ppc-xlate.pl: $!";
74
75 $sp="r1";
76 $toc="r2";
77 $rp="r3";       $ovf="r3";
78 $ap="r4";
79 $bp="r5";
80 $np="r6";
81 $n0="r7";
82 $num="r8";
83 $rp="r9";       # $rp is reassigned
84 $aj="r10";
85 $nj="r11";
86 $tj="r12";
87 # non-volatile registers
88 $i="r14";
89 $j="r15";
90 $tp="r16";
91 $m0="r17";
92 $m1="r18";
93 $lo0="r19";
94 $hi0="r20";
95 $lo1="r21";
96 $hi1="r22";
97 $alo="r23";
98 $ahi="r24";
99 $nlo="r25";
100 #
101 $nhi="r0";
102
103 $code=<<___;
104 .machine "any"
105 .text
106
107 .globl  .bn_mul_mont
108 .align  4
109 .bn_mul_mont:
110         cmpwi   $num,4
111         mr      $rp,r3          ; $rp is reassigned
112         li      r3,0
113         bltlr
114
115         slwi    $num,$num,`log($BNSZ)/log(2)`
116         li      $tj,-4096
117         addi    $ovf,$num,`$FRAME+$RZONE`
118         subf    $ovf,$ovf,$sp   ; $sp-$ovf
119         and     $ovf,$ovf,$tj   ; minimize TLB usage
120         subf    $ovf,$sp,$ovf   ; $ovf-$sp
121         srwi    $num,$num,`log($BNSZ)/log(2)`
122         $STUX   $sp,$sp,$ovf
123
124         $PUSH   r14,`4*$SIZE_T`($sp)
125         $PUSH   r15,`5*$SIZE_T`($sp)
126         $PUSH   r16,`6*$SIZE_T`($sp)
127         $PUSH   r17,`7*$SIZE_T`($sp)
128         $PUSH   r18,`8*$SIZE_T`($sp)
129         $PUSH   r19,`9*$SIZE_T`($sp)
130         $PUSH   r20,`10*$SIZE_T`($sp)
131         $PUSH   r21,`11*$SIZE_T`($sp)
132         $PUSH   r22,`12*$SIZE_T`($sp)
133         $PUSH   r23,`13*$SIZE_T`($sp)
134         $PUSH   r24,`14*$SIZE_T`($sp)
135         $PUSH   r25,`15*$SIZE_T`($sp)
136
137         $LD     $n0,0($n0)      ; pull n0[0] value
138         addi    $num,$num,-2    ; adjust $num for counter register
139 \f
140         $LD     $m0,0($bp)      ; m0=bp[0]
141         $LD     $aj,0($ap)      ; ap[0]
142         addi    $tp,$sp,$FRAME
143         $UMULL  $lo0,$aj,$m0    ; ap[0]*bp[0]
144         $UMULH  $hi0,$aj,$m0
145
146         $LD     $aj,$BNSZ($ap)  ; ap[1]
147         $LD     $nj,0($np)      ; np[0]
148
149         $UMULL  $m1,$lo0,$n0    ; "tp[0]"*n0
150
151         $UMULL  $alo,$aj,$m0    ; ap[1]*bp[0]
152         $UMULH  $ahi,$aj,$m0
153
154         $UMULL  $lo1,$nj,$m1    ; np[0]*m1
155         $UMULH  $hi1,$nj,$m1
156         $LD     $nj,$BNSZ($np)  ; np[1]
157         addc    $lo1,$lo1,$lo0
158         addze   $hi1,$hi1
159
160         $UMULL  $nlo,$nj,$m1    ; np[1]*m1
161         $UMULH  $nhi,$nj,$m1
162
163         mtctr   $num
164         li      $j,`2*$BNSZ`
165 .align  4
166 L1st:
167         $LDX    $aj,$ap,$j      ; ap[j]
168         addc    $lo0,$alo,$hi0
169         $LDX    $nj,$np,$j      ; np[j]
170         addze   $hi0,$ahi
171         $UMULL  $alo,$aj,$m0    ; ap[j]*bp[0]
172         addc    $lo1,$nlo,$hi1
173         $UMULH  $ahi,$aj,$m0
174         addze   $hi1,$nhi
175         $UMULL  $nlo,$nj,$m1    ; np[j]*m1
176         addc    $lo1,$lo1,$lo0  ; np[j]*m1+ap[j]*bp[0]
177         $UMULH  $nhi,$nj,$m1
178         addze   $hi1,$hi1
179         $ST     $lo1,0($tp)     ; tp[j-1]
180
181         addi    $j,$j,$BNSZ     ; j++
182         addi    $tp,$tp,$BNSZ   ; tp++
183         bdnz-   L1st
184 ;L1st
185         addc    $lo0,$alo,$hi0
186         addze   $hi0,$ahi
187
188         addc    $lo1,$nlo,$hi1
189         addze   $hi1,$nhi
190         addc    $lo1,$lo1,$lo0  ; np[j]*m1+ap[j]*bp[0]
191         addze   $hi1,$hi1
192         $ST     $lo1,0($tp)     ; tp[j-1]
193
194         li      $ovf,0
195         addc    $hi1,$hi1,$hi0
196         addze   $ovf,$ovf       ; upmost overflow bit
197         $ST     $hi1,$BNSZ($tp)
198 \f
199         li      $i,$BNSZ
200 .align  4
201 Louter:
202         $LDX    $m0,$bp,$i      ; m0=bp[i]
203         $LD     $aj,0($ap)      ; ap[0]
204         addi    $tp,$sp,$FRAME
205         $LD     $tj,$FRAME($sp) ; tp[0]
206         $UMULL  $lo0,$aj,$m0    ; ap[0]*bp[i]
207         $UMULH  $hi0,$aj,$m0
208         $LD     $aj,$BNSZ($ap)  ; ap[1]
209         $LD     $nj,0($np)      ; np[0]
210         addc    $lo0,$lo0,$tj   ; ap[0]*bp[i]+tp[0]
211         $UMULL  $alo,$aj,$m0    ; ap[j]*bp[i]
212         addze   $hi0,$hi0
213         $UMULL  $m1,$lo0,$n0    ; tp[0]*n0
214         $UMULH  $ahi,$aj,$m0
215         $UMULL  $lo1,$nj,$m1    ; np[0]*m1
216         $UMULH  $hi1,$nj,$m1
217         $LD     $nj,$BNSZ($np)  ; np[1]
218         addc    $lo1,$lo1,$lo0
219         $UMULL  $nlo,$nj,$m1    ; np[1]*m1
220         addze   $hi1,$hi1
221         $UMULH  $nhi,$nj,$m1
222 \f
223         mtctr   $num
224         li      $j,`2*$BNSZ`
225 .align  4
226 Linner:
227         $LDX    $aj,$ap,$j      ; ap[j]
228         addc    $lo0,$alo,$hi0
229         $LD     $tj,$BNSZ($tp)  ; tp[j]
230         addze   $hi0,$ahi
231         $LDX    $nj,$np,$j      ; np[j]
232         addc    $lo1,$nlo,$hi1
233         $UMULL  $alo,$aj,$m0    ; ap[j]*bp[i]
234         addze   $hi1,$nhi
235         $UMULH  $ahi,$aj,$m0
236         addc    $lo0,$lo0,$tj   ; ap[j]*bp[i]+tp[j]
237         $UMULL  $nlo,$nj,$m1    ; np[j]*m1
238         addze   $hi0,$hi0
239         $UMULH  $nhi,$nj,$m1
240         addc    $lo1,$lo1,$lo0  ; np[j]*m1+ap[j]*bp[i]+tp[j]
241         addi    $j,$j,$BNSZ     ; j++
242         addze   $hi1,$hi1
243         $ST     $lo1,0($tp)     ; tp[j-1]
244         addi    $tp,$tp,$BNSZ   ; tp++
245         bdnz-   Linner
246 ;Linner
247         $LD     $tj,$BNSZ($tp)  ; tp[j]
248         addc    $lo0,$alo,$hi0
249         addze   $hi0,$ahi
250         addc    $lo0,$lo0,$tj   ; ap[j]*bp[i]+tp[j]
251         addze   $hi0,$hi0
252
253         addc    $lo1,$nlo,$hi1
254         addze   $hi1,$nhi
255         addc    $lo1,$lo1,$lo0  ; np[j]*m1+ap[j]*bp[i]+tp[j]
256         addze   $hi1,$hi1
257         $ST     $lo1,0($tp)     ; tp[j-1]
258
259         addic   $ovf,$ovf,-1    ; move upmost overflow to XER[CA]
260         li      $ovf,0
261         adde    $hi1,$hi1,$hi0
262         addze   $ovf,$ovf
263         $ST     $hi1,$BNSZ($tp)
264 ;
265         slwi    $tj,$num,`log($BNSZ)/log(2)`
266         $UCMP   $i,$tj
267         addi    $i,$i,$BNSZ
268         ble-    Louter
269 \f
270         $SHRI.  $nj,$nj,$BITS-2 ; check boundary condition
271         addi    $num,$num,2     ; restore $num
272         subfc   $j,$j,$j        ; j=0 and "clear" XER[CA]
273         addi    $tp,$sp,$FRAME
274         addi    $ap,$sp,$FRAME
275         mtctr   $num
276         beq     Lcopy           ; boundary condition is met
277
278 .align  4
279 Lsub:   $LDX    $tj,$tp,$j
280         $LDX    $nj,$np,$j
281         subfe   $aj,$nj,$tj     ; tp[j]-np[j]
282         $STX    $aj,$rp,$j
283         addi    $j,$j,$BNSZ
284         bdnz-   Lsub
285
286         li      $j,0
287         mtctr   $num
288         subfe   $ovf,$j,$ovf    ; handle upmost overflow bit
289         and     $ap,$tp,$ovf
290         andc    $np,$rp,$ovf
291         or      $ap,$ap,$np     ; ap=borrow?tp:rp
292
293 .align  4
294 Lcopy:                          ; copy or in-place refresh
295         $LDX    $tj,$ap,$j
296         $STX    $tj,$rp,$j
297         $STX    $j,$tp,$j       ; zap at once
298         addi    $j,$j,$BNSZ
299         bdnz-   Lcopy
300
301         $POP    r14,`4*$SIZE_T`($sp)
302         $POP    r15,`5*$SIZE_T`($sp)
303         $POP    r16,`6*$SIZE_T`($sp)
304         $POP    r17,`7*$SIZE_T`($sp)
305         $POP    r18,`8*$SIZE_T`($sp)
306         $POP    r19,`9*$SIZE_T`($sp)
307         $POP    r20,`10*$SIZE_T`($sp)
308         $POP    r21,`11*$SIZE_T`($sp)
309         $POP    r22,`12*$SIZE_T`($sp)
310         $POP    r23,`13*$SIZE_T`($sp)
311         $POP    r24,`14*$SIZE_T`($sp)
312         $POP    r25,`15*$SIZE_T`($sp)
313         $POP    $sp,0($sp)
314         li      r3,1
315         blr
316         .long   0
317 .asciz  "Montgomery Multiplication for PPC, CRYPTOGAMS by <appro\@fy.chalmers.se>"
318 ___
319
320 $code =~ s/\`([^\`]*)\`/eval $1/gem;
321 print $code;
322 close STDOUT;