7a25b1ec9b6226d0ea68e7897e3404dfc1e4175a
[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";       $ovf="r3";
90 $ap="r4";
91 $bp="r5";
92 $np="r6";
93 $n0="r7";
94 $num="r8";
95 $rp="r9";       # $rp is reassigned
96 $aj="r10";
97 $nj="r11";
98 $tj="r12";
99 # non-volatile registers
100 $i="r20";
101 $j="r21";
102 $tp="r22";
103 $m0="r23";
104 $m1="r24";
105 $lo0="r25";
106 $hi0="r26";
107 $lo1="r27";
108 $hi1="r28";
109 $alo="r29";
110 $ahi="r30";
111 $nlo="r31";
112 #
113 $nhi="r0";
114
115 $code=<<___;
116 .machine "any"
117 .text
118
119 .globl  .bn_mul_mont_int
120 .align  4
121 .bn_mul_mont_int:
122         cmpwi   $num,4
123         mr      $rp,r3          ; $rp is reassigned
124         li      r3,0
125         bltlr
126 ___
127 $code.=<<___ if ($BNSZ==4);
128         cmpwi   $num,32         ; longer key performance is not better
129         bgelr
130 ___
131 $code.=<<___;
132         slwi    $num,$num,`log($BNSZ)/log(2)`
133         li      $tj,-4096
134         addi    $ovf,$num,$FRAME
135         subf    $ovf,$ovf,$sp   ; $sp-$ovf
136         and     $ovf,$ovf,$tj   ; minimize TLB usage
137         subf    $ovf,$sp,$ovf   ; $ovf-$sp
138         mr      $tj,$sp
139         srwi    $num,$num,`log($BNSZ)/log(2)`
140         $STUX   $sp,$sp,$ovf
141
142         $PUSH   r20,`-12*$SIZE_T`($tj)
143         $PUSH   r21,`-11*$SIZE_T`($tj)
144         $PUSH   r22,`-10*$SIZE_T`($tj)
145         $PUSH   r23,`-9*$SIZE_T`($tj)
146         $PUSH   r24,`-8*$SIZE_T`($tj)
147         $PUSH   r25,`-7*$SIZE_T`($tj)
148         $PUSH   r26,`-6*$SIZE_T`($tj)
149         $PUSH   r27,`-5*$SIZE_T`($tj)
150         $PUSH   r28,`-4*$SIZE_T`($tj)
151         $PUSH   r29,`-3*$SIZE_T`($tj)
152         $PUSH   r30,`-2*$SIZE_T`($tj)
153         $PUSH   r31,`-1*$SIZE_T`($tj)
154
155         $LD     $n0,0($n0)      ; pull n0[0] value
156         addi    $num,$num,-2    ; adjust $num for counter register
157 \f
158         $LD     $m0,0($bp)      ; m0=bp[0]
159         $LD     $aj,0($ap)      ; ap[0]
160         addi    $tp,$sp,$LOCALS
161         $UMULL  $lo0,$aj,$m0    ; ap[0]*bp[0]
162         $UMULH  $hi0,$aj,$m0
163
164         $LD     $aj,$BNSZ($ap)  ; ap[1]
165         $LD     $nj,0($np)      ; np[0]
166
167         $UMULL  $m1,$lo0,$n0    ; "tp[0]"*n0
168
169         $UMULL  $alo,$aj,$m0    ; ap[1]*bp[0]
170         $UMULH  $ahi,$aj,$m0
171
172         $UMULL  $lo1,$nj,$m1    ; np[0]*m1
173         $UMULH  $hi1,$nj,$m1
174         $LD     $nj,$BNSZ($np)  ; np[1]
175         addc    $lo1,$lo1,$lo0
176         addze   $hi1,$hi1
177
178         $UMULL  $nlo,$nj,$m1    ; np[1]*m1
179         $UMULH  $nhi,$nj,$m1
180
181         mtctr   $num
182         li      $j,`2*$BNSZ`
183 .align  4
184 L1st:
185         $LDX    $aj,$ap,$j      ; ap[j]
186         addc    $lo0,$alo,$hi0
187         $LDX    $nj,$np,$j      ; np[j]
188         addze   $hi0,$ahi
189         $UMULL  $alo,$aj,$m0    ; ap[j]*bp[0]
190         addc    $lo1,$nlo,$hi1
191         $UMULH  $ahi,$aj,$m0
192         addze   $hi1,$nhi
193         $UMULL  $nlo,$nj,$m1    ; np[j]*m1
194         addc    $lo1,$lo1,$lo0  ; np[j]*m1+ap[j]*bp[0]
195         $UMULH  $nhi,$nj,$m1
196         addze   $hi1,$hi1
197         $ST     $lo1,0($tp)     ; tp[j-1]
198
199         addi    $j,$j,$BNSZ     ; j++
200         addi    $tp,$tp,$BNSZ   ; tp++
201         bdnz    L1st
202 ;L1st
203         addc    $lo0,$alo,$hi0
204         addze   $hi0,$ahi
205
206         addc    $lo1,$nlo,$hi1
207         addze   $hi1,$nhi
208         addc    $lo1,$lo1,$lo0  ; np[j]*m1+ap[j]*bp[0]
209         addze   $hi1,$hi1
210         $ST     $lo1,0($tp)     ; tp[j-1]
211
212         li      $ovf,0
213         addc    $hi1,$hi1,$hi0
214         addze   $ovf,$ovf       ; upmost overflow bit
215         $ST     $hi1,$BNSZ($tp)
216 \f
217         li      $i,$BNSZ
218 .align  4
219 Louter:
220         $LDX    $m0,$bp,$i      ; m0=bp[i]
221         $LD     $aj,0($ap)      ; ap[0]
222         addi    $tp,$sp,$LOCALS
223         $LD     $tj,$LOCALS($sp); tp[0]
224         $UMULL  $lo0,$aj,$m0    ; ap[0]*bp[i]
225         $UMULH  $hi0,$aj,$m0
226         $LD     $aj,$BNSZ($ap)  ; ap[1]
227         $LD     $nj,0($np)      ; np[0]
228         addc    $lo0,$lo0,$tj   ; ap[0]*bp[i]+tp[0]
229         $UMULL  $alo,$aj,$m0    ; ap[j]*bp[i]
230         addze   $hi0,$hi0
231         $UMULL  $m1,$lo0,$n0    ; tp[0]*n0
232         $UMULH  $ahi,$aj,$m0
233         $UMULL  $lo1,$nj,$m1    ; np[0]*m1
234         $UMULH  $hi1,$nj,$m1
235         $LD     $nj,$BNSZ($np)  ; np[1]
236         addc    $lo1,$lo1,$lo0
237         $UMULL  $nlo,$nj,$m1    ; np[1]*m1
238         addze   $hi1,$hi1
239         $UMULH  $nhi,$nj,$m1
240 \f
241         mtctr   $num
242         li      $j,`2*$BNSZ`
243 .align  4
244 Linner:
245         $LDX    $aj,$ap,$j      ; ap[j]
246         addc    $lo0,$alo,$hi0
247         $LD     $tj,$BNSZ($tp)  ; tp[j]
248         addze   $hi0,$ahi
249         $LDX    $nj,$np,$j      ; np[j]
250         addc    $lo1,$nlo,$hi1
251         $UMULL  $alo,$aj,$m0    ; ap[j]*bp[i]
252         addze   $hi1,$nhi
253         $UMULH  $ahi,$aj,$m0
254         addc    $lo0,$lo0,$tj   ; ap[j]*bp[i]+tp[j]
255         $UMULL  $nlo,$nj,$m1    ; np[j]*m1
256         addze   $hi0,$hi0
257         $UMULH  $nhi,$nj,$m1
258         addc    $lo1,$lo1,$lo0  ; np[j]*m1+ap[j]*bp[i]+tp[j]
259         addi    $j,$j,$BNSZ     ; j++
260         addze   $hi1,$hi1
261         $ST     $lo1,0($tp)     ; tp[j-1]
262         addi    $tp,$tp,$BNSZ   ; tp++
263         bdnz    Linner
264 ;Linner
265         $LD     $tj,$BNSZ($tp)  ; tp[j]
266         addc    $lo0,$alo,$hi0
267         addze   $hi0,$ahi
268         addc    $lo0,$lo0,$tj   ; ap[j]*bp[i]+tp[j]
269         addze   $hi0,$hi0
270
271         addc    $lo1,$nlo,$hi1
272         addze   $hi1,$nhi
273         addc    $lo1,$lo1,$lo0  ; np[j]*m1+ap[j]*bp[i]+tp[j]
274         addze   $hi1,$hi1
275         $ST     $lo1,0($tp)     ; tp[j-1]
276
277         addic   $ovf,$ovf,-1    ; move upmost overflow to XER[CA]
278         li      $ovf,0
279         adde    $hi1,$hi1,$hi0
280         addze   $ovf,$ovf
281         $ST     $hi1,$BNSZ($tp)
282 ;
283         slwi    $tj,$num,`log($BNSZ)/log(2)`
284         $UCMP   $i,$tj
285         addi    $i,$i,$BNSZ
286         ble     Louter
287 \f
288         addi    $num,$num,2     ; restore $num
289         subfc   $j,$j,$j        ; j=0 and "clear" XER[CA]
290         addi    $tp,$sp,$LOCALS
291         mtctr   $num
292
293 .align  4
294 Lsub:   $LDX    $tj,$tp,$j
295         $LDX    $nj,$np,$j
296         subfe   $aj,$nj,$tj     ; tp[j]-np[j]
297         $STX    $aj,$rp,$j
298         addi    $j,$j,$BNSZ
299         bdnz    Lsub
300
301         li      $j,0
302         mtctr   $num
303         subfe   $ovf,$j,$ovf    ; handle upmost overflow bit
304         and     $ap,$tp,$ovf
305         andc    $np,$rp,$ovf
306         or      $ap,$ap,$np     ; ap=borrow?tp:rp
307
308 .align  4
309 Lcopy:                          ; copy or in-place refresh
310         $LDX    $tj,$ap,$j
311         $STX    $tj,$rp,$j
312         $STX    $j,$tp,$j       ; zap at once
313         addi    $j,$j,$BNSZ
314         bdnz    Lcopy
315
316         $POP    $tj,0($sp)
317         li      r3,1
318         $POP    r20,`-12*$SIZE_T`($tj)
319         $POP    r21,`-11*$SIZE_T`($tj)
320         $POP    r22,`-10*$SIZE_T`($tj)
321         $POP    r23,`-9*$SIZE_T`($tj)
322         $POP    r24,`-8*$SIZE_T`($tj)
323         $POP    r25,`-7*$SIZE_T`($tj)
324         $POP    r26,`-6*$SIZE_T`($tj)
325         $POP    r27,`-5*$SIZE_T`($tj)
326         $POP    r28,`-4*$SIZE_T`($tj)
327         $POP    r29,`-3*$SIZE_T`($tj)
328         $POP    r30,`-2*$SIZE_T`($tj)
329         $POP    r31,`-1*$SIZE_T`($tj)
330         mr      $sp,$tj
331         blr
332         .long   0
333         .byte   0,12,4,0,0x80,12,6,0
334         .long   0
335 .size   .bn_mul_mont_int,.-.bn_mul_mont_int
336
337 .asciz  "Montgomery Multiplication for PPC, CRYPTOGAMS by <appro\@openssl.org>"
338 ___
339
340 $code =~ s/\`([^\`]*)\`/eval $1/gem;
341 print $code;
342 close STDOUT;