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