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 # ====================================================================
12 # Performance improvement over vanilla C code varies from 85% to 45%
13 # depending on key length and benchmark. Unfortunately in this context
14 # these are not very impressive results [for code that utilizes "wide"
15 # 64x64=128-bit multiplication, which is not commonly available to C
16 # programmers], at least hand-coded bn_asm.c replacement is known to
17 # provide 30-40% better results for longest keys. Well, on a second
18 # thought it's not very surprising, because z-CPUs are single-issue
19 # and _strictly_ in-order execution, while bn_mul_mont is more or less
20 # dependent on CPU ability to pipe-line instructions and have several
21 # of them "in-flight" at the same time. I mean while other methods,
22 # for example Karatsuba, aim to minimize amount of multiplications at
23 # the cost of other operations increase, bn_mul_mont aim to neatly
24 # "overlap" multiplications and the other operations [and on most
25 # platforms even minimize the amount of the other operations, in
26 # particular references to memory]. But it's possible to improve this
27 # module performance by implementing dedicated squaring code-path and
28 # possibly by unrolling loops...
34 $rp="%r2"; # BN_ULONG *rp,
35 $ap="%r3"; # const BN_ULONG *ap,
36 $bp="%r4"; # const BN_ULONG *bp,
37 $np="%r5"; # const BN_ULONG *np,
38 $n0="%r6"; # const BN_ULONG *n0,
39 #$num="160(%r15)" # int num);
56 .type bn_mul_mont,\@function
58 lgf $num,164($sp) # pull $num
59 sla $num,3 # $num to enumerate bytes
60 la $rp,0($num,$rp) # pointers to point at the vectors' ends
69 blr %r14 # if($num<16) return 0;
71 lcgr $num,$num # -$num
74 aghi $fp,-160-8 # leave room for carry bit
75 la $sp,0($num,$fp) # alloca
77 aghi $fp,160-8 # $fp to point at tp[$num-1]
79 la $bp,0($num,$bp) # restore $bp
80 lg $n0,0($n0) # pull n0
84 mlgr $ahi,$bi # ap[0]*bp[0]
87 lgr $mn0,$alo # "tp[0]"*n0
91 mlgr $nhi,$mn0 # np[0]*m1
92 algr $nlo,$alo # +="tp[0]"
100 mlgr $ahi,$bi # ap[j]*bp[0]
106 mlgr $nhi,$mn0 # np[j]*m1
109 alcgr $nhi,$NHI # +="tp[j]"
113 stg $nlo,0($j,$fp) # tp[j-1]=
119 alcgr $AHI,$AHI # upmost overflow bit
125 lg $bi,0($bp) # bp[i]
127 mlgr $ahi,$bi # ap[0]*bp[i]
128 alg $alo,8($num,$fp)# +=tp[0]
133 msgr $mn0,$n0 # tp[0]*n0
135 lg $nlo,0($num,$np)# np[0]
136 mlgr $nhi,$mn0 # np[0]*m1
137 algr $nlo,$alo # +="tp[0]"
145 mlgr $ahi,$bi # ap[j]*bp[i]
149 alg $alo,8($j,$fp) # +=tp[j]
153 mlgr $nhi,$mn0 # np[j]*m1
157 algr $nlo,$alo # +="tp[j]"
160 stg $nlo,0($j,$fp) # tp[j-1]=
167 alg $NHI,8($fp) # accumulate previous upmost overflow bit
169 alcgr $AHI,$ahi # new upmost overflow bit
174 clg $bp,16+32($fp) # compare to &bp[num]
179 $count=$bp; undef $bp;
182 lg $rp,16+16($fp) # reincarnate rp
187 sra $count,3 # incidentally clears "borrow"
188 .Lsub: lg $alo,0($j,$ap)
194 slbgr $AHI,$ahi # handle upmost carry
200 ogr $ap,$np # ap=borrow?tp:rp
203 .Lcopy: lg $alo,0($j,$ap) # copy or in-place refresh
204 stg $j,8($j,$fp) # zap tp
209 lmg %r6,%r15,16+48($fp)
210 lghi %r2,1 # signal "processed"
212 .size bn_mul_mont,.-bn_mul_mont
213 .string "Montgomery Multiplication for s390x, CRYPTOGAMS by <appro\@openssl.org>"