Update copyright; generated files.
[openssl.git] / crypto / bn / asm / sparcv9a-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 # October 2005
11 #
12 # "Teaser" Montgomery multiplication module for UltraSPARC. Why FPU?
13 # Because unlike integer multiplier, which simply stalls whole CPU,
14 # FPU is fully pipelined and can effectively emit 48 bit partial
15 # product every cycle. Why not blended SPARC v9? One can argue that
16 # making this module dependent on UltraSPARC VIS extension limits its
17 # binary compatibility. Well yes, it does exclude SPARC64 prior-V(!)
18 # implementations from compatibility matrix. But the rest, whole Sun
19 # UltraSPARC family and brand new Fujitsu's SPARC64 V, all support
20 # VIS extension instructions used in this module. This is considered
21 # good enough to not care about HAL SPARC64 users [if any] who have
22 # integer-only pure SPARCv9 module to "fall down" to.
23
24 # USI&II cores currently exhibit uniform 2x improvement [over pre-
25 # bn_mul_mont codebase] for all key lengths and benchmarks. On USIII
26 # performance improves few percents for shorter keys and worsens few
27 # percents for longer keys. This is because USIII integer multiplier
28 # is >3x faster than USI&II one, which is harder to match [but see
29 # TODO list below]. It should also be noted that SPARC64 V features
30 # out-of-order execution, which *might* mean that integer multiplier
31 # is pipelined, which in turn *might* be impossible to match... On
32 # additional note, SPARC64 V implements FP Multiply-Add instruction,
33 # which is perfectly usable in this context... In other words, as far
34 # as Fujitsu SPARC64 V goes, talk to the author:-)
35
36 # The implementation implies following "non-natural" limitations on
37 # input arguments:
38 # - num may not be less than 4;
39 # - num has to be even;
40 # Failure to meet either condition has no fatal effects, simply
41 # doesn't give any performance gain.
42
43 # TODO:
44 # - modulo-schedule inner loop for better performance (on in-order
45 #   execution core such as UltraSPARC this shall result in further
46 #   noticeable(!) improvement);
47 # - dedicated squaring procedure[?];
48
49 ######################################################################
50 # November 2006
51 #
52 # Modulo-scheduled inner loops allow to interleave floating point and
53 # integer instructions and minimize Read-After-Write penalties. This
54 # results in *further* 20-50% perfromance improvement [depending on
55 # key length, more for longer keys] on USI&II cores and 30-80% - on
56 # USIII&IV.
57
58 $output = pop;
59 open STDOUT,">$output";
60
61 $fname="bn_mul_mont_fpu";
62
63 $frame="STACK_FRAME";
64 $bias="STACK_BIAS";
65 $locals=64;
66
67 # In order to provide for 32-/64-bit ABI duality, I keep integers wider
68 # than 32 bit in %g1-%g4 and %o0-%o5. %l0-%l7 and %i0-%i5 are used
69 # exclusively for pointers, indexes and other small values...
70 # int bn_mul_mont(
71 $rp="%i0";      # BN_ULONG *rp,
72 $ap="%i1";      # const BN_ULONG *ap,
73 $bp="%i2";      # const BN_ULONG *bp,
74 $np="%i3";      # const BN_ULONG *np,
75 $n0="%i4";      # const BN_ULONG *n0,
76 $num="%i5";     # int num);
77
78 $tp="%l0";      # t[num]
79 $ap_l="%l1";    # a[num],n[num] are smashed to 32-bit words and saved
80 $ap_h="%l2";    # to these four vectors as double-precision FP values.
81 $np_l="%l3";    # This way a bunch of fxtods are eliminated in second
82 $np_h="%l4";    # loop and L1-cache aliasing is minimized...
83 $i="%l5";
84 $j="%l6";
85 $mask="%l7";    # 16-bit mask, 0xffff
86
87 $n0="%g4";      # reassigned(!) to "64-bit" register
88 $carry="%i4";   # %i4 reused(!) for a carry bit
89
90 # FP register naming chart
91 #
92 #     ..HILO
93 #       dcba
94 #   --------
95 #        LOa
96 #       LOb
97 #      LOc
98 #     LOd
99 #      HIa
100 #     HIb
101 #    HIc
102 #   HId
103 #    ..a
104 #   ..b
105 $ba="%f0";    $bb="%f2";    $bc="%f4";    $bd="%f6";
106 $na="%f8";    $nb="%f10";   $nc="%f12";   $nd="%f14";
107 $alo="%f16";  $alo_="%f17"; $ahi="%f18";  $ahi_="%f19";
108 $nlo="%f20";  $nlo_="%f21"; $nhi="%f22";  $nhi_="%f23";
109
110 $dota="%f24"; $dotb="%f26";
111
112 $aloa="%f32"; $alob="%f34"; $aloc="%f36"; $alod="%f38";
113 $ahia="%f40"; $ahib="%f42"; $ahic="%f44"; $ahid="%f46";
114 $nloa="%f48"; $nlob="%f50"; $nloc="%f52"; $nlod="%f54";
115 $nhia="%f56"; $nhib="%f58"; $nhic="%f60"; $nhid="%f62";
116
117 $ASI_FL16_P=0xD2;       # magic ASI value to engage 16-bit FP load
118
119 $code=<<___;
120 #include "sparc_arch.h"
121
122 .section        ".text",#alloc,#execinstr
123
124 .global $fname
125 .align  32
126 $fname:
127         save    %sp,-$frame-$locals,%sp
128
129         cmp     $num,4
130         bl,a,pn %icc,.Lret
131         clr     %i0
132         andcc   $num,1,%g0              ! $num has to be even...
133         bnz,a,pn %icc,.Lret
134         clr     %i0                     ! signal "unsupported input value"
135
136         srl     $num,1,$num
137         sethi   %hi(0xffff),$mask
138         ld      [%i4+0],$n0             ! $n0 reassigned, remember?
139         or      $mask,%lo(0xffff),$mask
140         ld      [%i4+4],%o0
141         sllx    %o0,32,%o0
142         or      %o0,$n0,$n0             ! $n0=n0[1].n0[0]
143
144         sll     $num,3,$num             ! num*=8
145
146         add     %sp,$bias,%o0           ! real top of stack
147         sll     $num,2,%o1
148         add     %o1,$num,%o1            ! %o1=num*5
149         sub     %o0,%o1,%o0
150         and     %o0,-2048,%o0           ! optimize TLB utilization
151         sub     %o0,$bias,%sp           ! alloca(5*num*8)
152
153         rd      %asi,%o7                ! save %asi
154         add     %sp,$bias+$frame+$locals,$tp
155         add     $tp,$num,$ap_l
156         add     $ap_l,$num,$ap_l        ! [an]p_[lh] point at the vectors' ends !
157         add     $ap_l,$num,$ap_h
158         add     $ap_h,$num,$np_l
159         add     $np_l,$num,$np_h
160
161         wr      %g0,$ASI_FL16_P,%asi    ! setup %asi for 16-bit FP loads
162
163         add     $rp,$num,$rp            ! readjust input pointers to point
164         add     $ap,$num,$ap            ! at the ends too...
165         add     $bp,$num,$bp
166         add     $np,$num,$np
167
168         stx     %o7,[%sp+$bias+$frame+48]       ! save %asi
169 \f
170         sub     %g0,$num,$i             ! i=-num
171         sub     %g0,$num,$j             ! j=-num
172
173         add     $ap,$j,%o3
174         add     $bp,$i,%o4
175
176         ld      [%o3+4],%g1             ! bp[0]
177         ld      [%o3+0],%o0
178         ld      [%o4+4],%g5             ! ap[0]
179         sllx    %g1,32,%g1
180         ld      [%o4+0],%o1
181         sllx    %g5,32,%g5
182         or      %g1,%o0,%o0
183         or      %g5,%o1,%o1
184
185         add     $np,$j,%o5
186
187         mulx    %o1,%o0,%o0             ! ap[0]*bp[0]
188         mulx    $n0,%o0,%o0             ! ap[0]*bp[0]*n0
189         stx     %o0,[%sp+$bias+$frame+0]
190
191         ld      [%o3+0],$alo_   ! load a[j] as pair of 32-bit words
192         fzeros  $alo
193         ld      [%o3+4],$ahi_
194         fzeros  $ahi
195         ld      [%o5+0],$nlo_   ! load n[j] as pair of 32-bit words
196         fzeros  $nlo
197         ld      [%o5+4],$nhi_
198         fzeros  $nhi
199
200         ! transfer b[i] to FPU as 4x16-bit values
201         ldda    [%o4+2]%asi,$ba
202         fxtod   $alo,$alo
203         ldda    [%o4+0]%asi,$bb
204         fxtod   $ahi,$ahi
205         ldda    [%o4+6]%asi,$bc
206         fxtod   $nlo,$nlo
207         ldda    [%o4+4]%asi,$bd
208         fxtod   $nhi,$nhi
209
210         ! transfer ap[0]*b[0]*n0 to FPU as 4x16-bit values
211         ldda    [%sp+$bias+$frame+6]%asi,$na
212         fxtod   $ba,$ba
213         ldda    [%sp+$bias+$frame+4]%asi,$nb
214         fxtod   $bb,$bb
215         ldda    [%sp+$bias+$frame+2]%asi,$nc
216         fxtod   $bc,$bc
217         ldda    [%sp+$bias+$frame+0]%asi,$nd
218         fxtod   $bd,$bd
219
220         std     $alo,[$ap_l+$j]         ! save smashed ap[j] in double format
221         fxtod   $na,$na
222         std     $ahi,[$ap_h+$j]
223         fxtod   $nb,$nb
224         std     $nlo,[$np_l+$j]         ! save smashed np[j] in double format
225         fxtod   $nc,$nc
226         std     $nhi,[$np_h+$j]
227         fxtod   $nd,$nd
228
229                 fmuld   $alo,$ba,$aloa
230                 fmuld   $nlo,$na,$nloa
231                 fmuld   $alo,$bb,$alob
232                 fmuld   $nlo,$nb,$nlob
233                 fmuld   $alo,$bc,$aloc
234         faddd   $aloa,$nloa,$nloa
235                 fmuld   $nlo,$nc,$nloc
236                 fmuld   $alo,$bd,$alod
237         faddd   $alob,$nlob,$nlob
238                 fmuld   $nlo,$nd,$nlod
239                 fmuld   $ahi,$ba,$ahia
240         faddd   $aloc,$nloc,$nloc
241                 fmuld   $nhi,$na,$nhia
242                 fmuld   $ahi,$bb,$ahib
243         faddd   $alod,$nlod,$nlod
244                 fmuld   $nhi,$nb,$nhib
245                 fmuld   $ahi,$bc,$ahic
246         faddd   $ahia,$nhia,$nhia
247                 fmuld   $nhi,$nc,$nhic
248                 fmuld   $ahi,$bd,$ahid
249         faddd   $ahib,$nhib,$nhib
250                 fmuld   $nhi,$nd,$nhid
251
252         faddd   $ahic,$nhic,$dota       ! $nhic
253         faddd   $ahid,$nhid,$dotb       ! $nhid
254
255         faddd   $nloc,$nhia,$nloc
256         faddd   $nlod,$nhib,$nlod
257
258         fdtox   $nloa,$nloa
259         fdtox   $nlob,$nlob
260         fdtox   $nloc,$nloc
261         fdtox   $nlod,$nlod
262
263         std     $nloa,[%sp+$bias+$frame+0]
264         add     $j,8,$j
265         std     $nlob,[%sp+$bias+$frame+8]
266         add     $ap,$j,%o4
267         std     $nloc,[%sp+$bias+$frame+16]
268         add     $np,$j,%o5
269         std     $nlod,[%sp+$bias+$frame+24]
270 \f
271         ld      [%o4+0],$alo_   ! load a[j] as pair of 32-bit words
272         fzeros  $alo
273         ld      [%o4+4],$ahi_
274         fzeros  $ahi
275         ld      [%o5+0],$nlo_   ! load n[j] as pair of 32-bit words
276         fzeros  $nlo
277         ld      [%o5+4],$nhi_
278         fzeros  $nhi
279
280         fxtod   $alo,$alo
281         fxtod   $ahi,$ahi
282         fxtod   $nlo,$nlo
283         fxtod   $nhi,$nhi
284
285         ldx     [%sp+$bias+$frame+0],%o0
286                 fmuld   $alo,$ba,$aloa
287         ldx     [%sp+$bias+$frame+8],%o1
288                 fmuld   $nlo,$na,$nloa
289         ldx     [%sp+$bias+$frame+16],%o2
290                 fmuld   $alo,$bb,$alob
291         ldx     [%sp+$bias+$frame+24],%o3
292                 fmuld   $nlo,$nb,$nlob
293
294         srlx    %o0,16,%o7
295         std     $alo,[$ap_l+$j]         ! save smashed ap[j] in double format
296                 fmuld   $alo,$bc,$aloc
297         add     %o7,%o1,%o1
298         std     $ahi,[$ap_h+$j]
299                 faddd   $aloa,$nloa,$nloa
300                 fmuld   $nlo,$nc,$nloc
301         srlx    %o1,16,%o7
302         std     $nlo,[$np_l+$j]         ! save smashed np[j] in double format
303                 fmuld   $alo,$bd,$alod
304         add     %o7,%o2,%o2
305         std     $nhi,[$np_h+$j]
306                 faddd   $alob,$nlob,$nlob
307                 fmuld   $nlo,$nd,$nlod
308         srlx    %o2,16,%o7
309                 fmuld   $ahi,$ba,$ahia
310         add     %o7,%o3,%o3             ! %o3.%o2[0..15].%o1[0..15].%o0[0..15]
311                 faddd   $aloc,$nloc,$nloc
312                 fmuld   $nhi,$na,$nhia
313         !and    %o0,$mask,%o0
314         !and    %o1,$mask,%o1
315         !and    %o2,$mask,%o2
316         !sllx   %o1,16,%o1
317         !sllx   %o2,32,%o2
318         !sllx   %o3,48,%o7
319         !or     %o1,%o0,%o0
320         !or     %o2,%o0,%o0
321         !or     %o7,%o0,%o0             ! 64-bit result
322         srlx    %o3,16,%g1              ! 34-bit carry
323                 fmuld   $ahi,$bb,$ahib
324
325         faddd   $alod,$nlod,$nlod
326                 fmuld   $nhi,$nb,$nhib
327                 fmuld   $ahi,$bc,$ahic
328         faddd   $ahia,$nhia,$nhia
329                 fmuld   $nhi,$nc,$nhic
330                 fmuld   $ahi,$bd,$ahid
331         faddd   $ahib,$nhib,$nhib
332                 fmuld   $nhi,$nd,$nhid
333
334         faddd   $dota,$nloa,$nloa
335         faddd   $dotb,$nlob,$nlob
336         faddd   $ahic,$nhic,$dota       ! $nhic
337         faddd   $ahid,$nhid,$dotb       ! $nhid
338
339         faddd   $nloc,$nhia,$nloc
340         faddd   $nlod,$nhib,$nlod
341
342         fdtox   $nloa,$nloa
343         fdtox   $nlob,$nlob
344         fdtox   $nloc,$nloc
345         fdtox   $nlod,$nlod
346
347         std     $nloa,[%sp+$bias+$frame+0]
348         std     $nlob,[%sp+$bias+$frame+8]
349         addcc   $j,8,$j
350         std     $nloc,[%sp+$bias+$frame+16]
351         bz,pn   %icc,.L1stskip
352         std     $nlod,[%sp+$bias+$frame+24]
353 \f
354 .align  32                      ! incidentally already aligned !
355 .L1st:
356         add     $ap,$j,%o4
357         add     $np,$j,%o5
358         ld      [%o4+0],$alo_   ! load a[j] as pair of 32-bit words
359         fzeros  $alo
360         ld      [%o4+4],$ahi_
361         fzeros  $ahi
362         ld      [%o5+0],$nlo_   ! load n[j] as pair of 32-bit words
363         fzeros  $nlo
364         ld      [%o5+4],$nhi_
365         fzeros  $nhi
366
367         fxtod   $alo,$alo
368         fxtod   $ahi,$ahi
369         fxtod   $nlo,$nlo
370         fxtod   $nhi,$nhi
371
372         ldx     [%sp+$bias+$frame+0],%o0
373                 fmuld   $alo,$ba,$aloa
374         ldx     [%sp+$bias+$frame+8],%o1
375                 fmuld   $nlo,$na,$nloa
376         ldx     [%sp+$bias+$frame+16],%o2
377                 fmuld   $alo,$bb,$alob
378         ldx     [%sp+$bias+$frame+24],%o3
379                 fmuld   $nlo,$nb,$nlob
380
381         srlx    %o0,16,%o7
382         std     $alo,[$ap_l+$j]         ! save smashed ap[j] in double format
383                 fmuld   $alo,$bc,$aloc
384         add     %o7,%o1,%o1
385         std     $ahi,[$ap_h+$j]
386                 faddd   $aloa,$nloa,$nloa
387                 fmuld   $nlo,$nc,$nloc
388         srlx    %o1,16,%o7
389         std     $nlo,[$np_l+$j]         ! save smashed np[j] in double format
390                 fmuld   $alo,$bd,$alod
391         add     %o7,%o2,%o2
392         std     $nhi,[$np_h+$j]
393                 faddd   $alob,$nlob,$nlob
394                 fmuld   $nlo,$nd,$nlod
395         srlx    %o2,16,%o7
396                 fmuld   $ahi,$ba,$ahia
397         add     %o7,%o3,%o3             ! %o3.%o2[0..15].%o1[0..15].%o0[0..15]
398         and     %o0,$mask,%o0
399                 faddd   $aloc,$nloc,$nloc
400                 fmuld   $nhi,$na,$nhia
401         and     %o1,$mask,%o1
402         and     %o2,$mask,%o2
403                 fmuld   $ahi,$bb,$ahib
404         sllx    %o1,16,%o1
405                 faddd   $alod,$nlod,$nlod
406                 fmuld   $nhi,$nb,$nhib
407         sllx    %o2,32,%o2
408                 fmuld   $ahi,$bc,$ahic
409         sllx    %o3,48,%o7
410         or      %o1,%o0,%o0
411                 faddd   $ahia,$nhia,$nhia
412                 fmuld   $nhi,$nc,$nhic
413         or      %o2,%o0,%o0
414                 fmuld   $ahi,$bd,$ahid
415         or      %o7,%o0,%o0             ! 64-bit result
416                 faddd   $ahib,$nhib,$nhib
417                 fmuld   $nhi,$nd,$nhid
418         addcc   %g1,%o0,%o0
419                 faddd   $dota,$nloa,$nloa
420         srlx    %o3,16,%g1              ! 34-bit carry
421                 faddd   $dotb,$nlob,$nlob
422         bcs,a   %xcc,.+8
423         add     %g1,1,%g1
424
425         stx     %o0,[$tp]               ! tp[j-1]=
426
427         faddd   $ahic,$nhic,$dota       ! $nhic
428         faddd   $ahid,$nhid,$dotb       ! $nhid
429
430         faddd   $nloc,$nhia,$nloc
431         faddd   $nlod,$nhib,$nlod
432
433         fdtox   $nloa,$nloa
434         fdtox   $nlob,$nlob
435         fdtox   $nloc,$nloc
436         fdtox   $nlod,$nlod
437
438         std     $nloa,[%sp+$bias+$frame+0]
439         std     $nlob,[%sp+$bias+$frame+8]
440         std     $nloc,[%sp+$bias+$frame+16]
441         std     $nlod,[%sp+$bias+$frame+24]
442
443         addcc   $j,8,$j
444         bnz,pt  %icc,.L1st
445         add     $tp,8,$tp
446 \f
447 .L1stskip:
448         fdtox   $dota,$dota
449         fdtox   $dotb,$dotb
450
451         ldx     [%sp+$bias+$frame+0],%o0
452         ldx     [%sp+$bias+$frame+8],%o1
453         ldx     [%sp+$bias+$frame+16],%o2
454         ldx     [%sp+$bias+$frame+24],%o3
455
456         srlx    %o0,16,%o7
457         std     $dota,[%sp+$bias+$frame+32]
458         add     %o7,%o1,%o1
459         std     $dotb,[%sp+$bias+$frame+40]
460         srlx    %o1,16,%o7
461         add     %o7,%o2,%o2
462         srlx    %o2,16,%o7
463         add     %o7,%o3,%o3             ! %o3.%o2[0..15].%o1[0..15].%o0[0..15]
464         and     %o0,$mask,%o0
465         and     %o1,$mask,%o1
466         and     %o2,$mask,%o2
467         sllx    %o1,16,%o1
468         sllx    %o2,32,%o2
469         sllx    %o3,48,%o7
470         or      %o1,%o0,%o0
471         or      %o2,%o0,%o0
472         or      %o7,%o0,%o0             ! 64-bit result
473         ldx     [%sp+$bias+$frame+32],%o4
474         addcc   %g1,%o0,%o0
475         ldx     [%sp+$bias+$frame+40],%o5
476         srlx    %o3,16,%g1              ! 34-bit carry
477         bcs,a   %xcc,.+8
478         add     %g1,1,%g1
479
480         stx     %o0,[$tp]               ! tp[j-1]=
481         add     $tp,8,$tp
482
483         srlx    %o4,16,%o7
484         add     %o7,%o5,%o5
485         and     %o4,$mask,%o4
486         sllx    %o5,16,%o7
487         or      %o7,%o4,%o4
488         addcc   %g1,%o4,%o4
489         srlx    %o5,48,%g1
490         bcs,a   %xcc,.+8
491         add     %g1,1,%g1
492
493         mov     %g1,$carry
494         stx     %o4,[$tp]               ! tp[num-1]=
495 \f
496         ba      .Louter
497         add     $i,8,$i
498 .align  32
499 .Louter:
500         sub     %g0,$num,$j             ! j=-num
501         add     %sp,$bias+$frame+$locals,$tp
502
503         add     $ap,$j,%o3
504         add     $bp,$i,%o4
505
506         ld      [%o3+4],%g1             ! bp[i]
507         ld      [%o3+0],%o0
508         ld      [%o4+4],%g5             ! ap[0]
509         sllx    %g1,32,%g1
510         ld      [%o4+0],%o1
511         sllx    %g5,32,%g5
512         or      %g1,%o0,%o0
513         or      %g5,%o1,%o1
514
515         ldx     [$tp],%o2               ! tp[0]
516         mulx    %o1,%o0,%o0
517         addcc   %o2,%o0,%o0
518         mulx    $n0,%o0,%o0             ! (ap[0]*bp[i]+t[0])*n0
519         stx     %o0,[%sp+$bias+$frame+0]
520
521         ! transfer b[i] to FPU as 4x16-bit values
522         ldda    [%o4+2]%asi,$ba
523         ldda    [%o4+0]%asi,$bb
524         ldda    [%o4+6]%asi,$bc
525         ldda    [%o4+4]%asi,$bd
526
527         ! transfer (ap[0]*b[i]+t[0])*n0 to FPU as 4x16-bit values
528         ldda    [%sp+$bias+$frame+6]%asi,$na
529         fxtod   $ba,$ba
530         ldda    [%sp+$bias+$frame+4]%asi,$nb
531         fxtod   $bb,$bb
532         ldda    [%sp+$bias+$frame+2]%asi,$nc
533         fxtod   $bc,$bc
534         ldda    [%sp+$bias+$frame+0]%asi,$nd
535         fxtod   $bd,$bd
536         ldd     [$ap_l+$j],$alo         ! load a[j] in double format
537         fxtod   $na,$na
538         ldd     [$ap_h+$j],$ahi
539         fxtod   $nb,$nb
540         ldd     [$np_l+$j],$nlo         ! load n[j] in double format
541         fxtod   $nc,$nc
542         ldd     [$np_h+$j],$nhi
543         fxtod   $nd,$nd
544
545                 fmuld   $alo,$ba,$aloa
546                 fmuld   $nlo,$na,$nloa
547                 fmuld   $alo,$bb,$alob
548                 fmuld   $nlo,$nb,$nlob
549                 fmuld   $alo,$bc,$aloc
550         faddd   $aloa,$nloa,$nloa
551                 fmuld   $nlo,$nc,$nloc
552                 fmuld   $alo,$bd,$alod
553         faddd   $alob,$nlob,$nlob
554                 fmuld   $nlo,$nd,$nlod
555                 fmuld   $ahi,$ba,$ahia
556         faddd   $aloc,$nloc,$nloc
557                 fmuld   $nhi,$na,$nhia
558                 fmuld   $ahi,$bb,$ahib
559         faddd   $alod,$nlod,$nlod
560                 fmuld   $nhi,$nb,$nhib
561                 fmuld   $ahi,$bc,$ahic
562         faddd   $ahia,$nhia,$nhia
563                 fmuld   $nhi,$nc,$nhic
564                 fmuld   $ahi,$bd,$ahid
565         faddd   $ahib,$nhib,$nhib
566                 fmuld   $nhi,$nd,$nhid
567
568         faddd   $ahic,$nhic,$dota       ! $nhic
569         faddd   $ahid,$nhid,$dotb       ! $nhid
570
571         faddd   $nloc,$nhia,$nloc
572         faddd   $nlod,$nhib,$nlod
573
574         fdtox   $nloa,$nloa
575         fdtox   $nlob,$nlob
576         fdtox   $nloc,$nloc
577         fdtox   $nlod,$nlod
578
579         std     $nloa,[%sp+$bias+$frame+0]
580         std     $nlob,[%sp+$bias+$frame+8]
581         std     $nloc,[%sp+$bias+$frame+16]
582         add     $j,8,$j
583         std     $nlod,[%sp+$bias+$frame+24]
584 \f
585         ldd     [$ap_l+$j],$alo         ! load a[j] in double format
586         ldd     [$ap_h+$j],$ahi
587         ldd     [$np_l+$j],$nlo         ! load n[j] in double format
588         ldd     [$np_h+$j],$nhi
589
590                 fmuld   $alo,$ba,$aloa
591                 fmuld   $nlo,$na,$nloa
592                 fmuld   $alo,$bb,$alob
593                 fmuld   $nlo,$nb,$nlob
594                 fmuld   $alo,$bc,$aloc
595         ldx     [%sp+$bias+$frame+0],%o0
596                 faddd   $aloa,$nloa,$nloa
597                 fmuld   $nlo,$nc,$nloc
598         ldx     [%sp+$bias+$frame+8],%o1
599                 fmuld   $alo,$bd,$alod
600         ldx     [%sp+$bias+$frame+16],%o2
601                 faddd   $alob,$nlob,$nlob
602                 fmuld   $nlo,$nd,$nlod
603         ldx     [%sp+$bias+$frame+24],%o3
604                 fmuld   $ahi,$ba,$ahia
605
606         srlx    %o0,16,%o7
607                 faddd   $aloc,$nloc,$nloc
608                 fmuld   $nhi,$na,$nhia
609         add     %o7,%o1,%o1
610                 fmuld   $ahi,$bb,$ahib
611         srlx    %o1,16,%o7
612                 faddd   $alod,$nlod,$nlod
613                 fmuld   $nhi,$nb,$nhib
614         add     %o7,%o2,%o2
615                 fmuld   $ahi,$bc,$ahic
616         srlx    %o2,16,%o7
617                 faddd   $ahia,$nhia,$nhia
618                 fmuld   $nhi,$nc,$nhic
619         add     %o7,%o3,%o3             ! %o3.%o2[0..15].%o1[0..15].%o0[0..15]
620         ! why?
621         and     %o0,$mask,%o0
622                 fmuld   $ahi,$bd,$ahid
623         and     %o1,$mask,%o1
624         and     %o2,$mask,%o2
625                 faddd   $ahib,$nhib,$nhib
626                 fmuld   $nhi,$nd,$nhid
627         sllx    %o1,16,%o1
628                 faddd   $dota,$nloa,$nloa
629         sllx    %o2,32,%o2
630                 faddd   $dotb,$nlob,$nlob
631         sllx    %o3,48,%o7
632         or      %o1,%o0,%o0
633                 faddd   $ahic,$nhic,$dota       ! $nhic
634         or      %o2,%o0,%o0
635                 faddd   $ahid,$nhid,$dotb       ! $nhid
636         or      %o7,%o0,%o0             ! 64-bit result
637         ldx     [$tp],%o7
638                 faddd   $nloc,$nhia,$nloc
639         addcc   %o7,%o0,%o0
640         ! end-of-why?
641                 faddd   $nlod,$nhib,$nlod
642         srlx    %o3,16,%g1              ! 34-bit carry
643                 fdtox   $nloa,$nloa
644         bcs,a   %xcc,.+8
645         add     %g1,1,%g1
646
647         fdtox   $nlob,$nlob
648         fdtox   $nloc,$nloc
649         fdtox   $nlod,$nlod
650
651         std     $nloa,[%sp+$bias+$frame+0]
652         std     $nlob,[%sp+$bias+$frame+8]
653         addcc   $j,8,$j
654         std     $nloc,[%sp+$bias+$frame+16]
655         bz,pn   %icc,.Linnerskip
656         std     $nlod,[%sp+$bias+$frame+24]
657 \f
658         ba      .Linner
659         nop
660 .align  32
661 .Linner:
662         ldd     [$ap_l+$j],$alo         ! load a[j] in double format
663         ldd     [$ap_h+$j],$ahi
664         ldd     [$np_l+$j],$nlo         ! load n[j] in double format
665         ldd     [$np_h+$j],$nhi
666
667                 fmuld   $alo,$ba,$aloa
668                 fmuld   $nlo,$na,$nloa
669                 fmuld   $alo,$bb,$alob
670                 fmuld   $nlo,$nb,$nlob
671                 fmuld   $alo,$bc,$aloc
672         ldx     [%sp+$bias+$frame+0],%o0
673                 faddd   $aloa,$nloa,$nloa
674                 fmuld   $nlo,$nc,$nloc
675         ldx     [%sp+$bias+$frame+8],%o1
676                 fmuld   $alo,$bd,$alod
677         ldx     [%sp+$bias+$frame+16],%o2
678                 faddd   $alob,$nlob,$nlob
679                 fmuld   $nlo,$nd,$nlod
680         ldx     [%sp+$bias+$frame+24],%o3
681                 fmuld   $ahi,$ba,$ahia
682
683         srlx    %o0,16,%o7
684                 faddd   $aloc,$nloc,$nloc
685                 fmuld   $nhi,$na,$nhia
686         add     %o7,%o1,%o1
687                 fmuld   $ahi,$bb,$ahib
688         srlx    %o1,16,%o7
689                 faddd   $alod,$nlod,$nlod
690                 fmuld   $nhi,$nb,$nhib
691         add     %o7,%o2,%o2
692                 fmuld   $ahi,$bc,$ahic
693         srlx    %o2,16,%o7
694                 faddd   $ahia,$nhia,$nhia
695                 fmuld   $nhi,$nc,$nhic
696         add     %o7,%o3,%o3             ! %o3.%o2[0..15].%o1[0..15].%o0[0..15]
697         and     %o0,$mask,%o0
698                 fmuld   $ahi,$bd,$ahid
699         and     %o1,$mask,%o1
700         and     %o2,$mask,%o2
701                 faddd   $ahib,$nhib,$nhib
702                 fmuld   $nhi,$nd,$nhid
703         sllx    %o1,16,%o1
704                 faddd   $dota,$nloa,$nloa
705         sllx    %o2,32,%o2
706                 faddd   $dotb,$nlob,$nlob
707         sllx    %o3,48,%o7
708         or      %o1,%o0,%o0
709                 faddd   $ahic,$nhic,$dota       ! $nhic
710         or      %o2,%o0,%o0
711                 faddd   $ahid,$nhid,$dotb       ! $nhid
712         or      %o7,%o0,%o0             ! 64-bit result
713                 faddd   $nloc,$nhia,$nloc
714         addcc   %g1,%o0,%o0
715         ldx     [$tp+8],%o7             ! tp[j]
716                 faddd   $nlod,$nhib,$nlod
717         srlx    %o3,16,%g1              ! 34-bit carry
718                 fdtox   $nloa,$nloa
719         bcs,a   %xcc,.+8
720         add     %g1,1,%g1
721                 fdtox   $nlob,$nlob
722         addcc   %o7,%o0,%o0
723                 fdtox   $nloc,$nloc
724         bcs,a   %xcc,.+8
725         add     %g1,1,%g1
726
727         stx     %o0,[$tp]               ! tp[j-1]
728                 fdtox   $nlod,$nlod
729
730         std     $nloa,[%sp+$bias+$frame+0]
731         std     $nlob,[%sp+$bias+$frame+8]
732         std     $nloc,[%sp+$bias+$frame+16]
733         addcc   $j,8,$j
734         std     $nlod,[%sp+$bias+$frame+24]
735         bnz,pt  %icc,.Linner
736         add     $tp,8,$tp
737 \f
738 .Linnerskip:
739         fdtox   $dota,$dota
740         fdtox   $dotb,$dotb
741
742         ldx     [%sp+$bias+$frame+0],%o0
743         ldx     [%sp+$bias+$frame+8],%o1
744         ldx     [%sp+$bias+$frame+16],%o2
745         ldx     [%sp+$bias+$frame+24],%o3
746
747         srlx    %o0,16,%o7
748         std     $dota,[%sp+$bias+$frame+32]
749         add     %o7,%o1,%o1
750         std     $dotb,[%sp+$bias+$frame+40]
751         srlx    %o1,16,%o7
752         add     %o7,%o2,%o2
753         srlx    %o2,16,%o7
754         add     %o7,%o3,%o3             ! %o3.%o2[0..15].%o1[0..15].%o0[0..15]
755         and     %o0,$mask,%o0
756         and     %o1,$mask,%o1
757         and     %o2,$mask,%o2
758         sllx    %o1,16,%o1
759         sllx    %o2,32,%o2
760         sllx    %o3,48,%o7
761         or      %o1,%o0,%o0
762         or      %o2,%o0,%o0
763         ldx     [%sp+$bias+$frame+32],%o4
764         or      %o7,%o0,%o0             ! 64-bit result
765         ldx     [%sp+$bias+$frame+40],%o5
766         addcc   %g1,%o0,%o0
767         ldx     [$tp+8],%o7             ! tp[j]
768         srlx    %o3,16,%g1              ! 34-bit carry
769         bcs,a   %xcc,.+8
770         add     %g1,1,%g1
771
772         addcc   %o7,%o0,%o0
773         bcs,a   %xcc,.+8
774         add     %g1,1,%g1
775
776         stx     %o0,[$tp]               ! tp[j-1]
777         add     $tp,8,$tp
778
779         srlx    %o4,16,%o7
780         add     %o7,%o5,%o5
781         and     %o4,$mask,%o4
782         sllx    %o5,16,%o7
783         or      %o7,%o4,%o4
784         addcc   %g1,%o4,%o4
785         srlx    %o5,48,%g1
786         bcs,a   %xcc,.+8
787         add     %g1,1,%g1
788
789         addcc   $carry,%o4,%o4
790         stx     %o4,[$tp]               ! tp[num-1]
791         mov     %g1,$carry
792         bcs,a   %xcc,.+8
793         add     $carry,1,$carry
794
795         addcc   $i,8,$i
796         bnz     %icc,.Louter
797         nop
798 \f
799         add     $tp,8,$tp               ! adjust tp to point at the end
800         orn     %g0,%g0,%g4
801         sub     %g0,$num,%o7            ! n=-num
802         ba      .Lsub
803         subcc   %g0,%g0,%g0             ! clear %icc.c
804
805 .align  32
806 .Lsub:
807         ldx     [$tp+%o7],%o0
808         add     $np,%o7,%g1
809         ld      [%g1+0],%o2
810         ld      [%g1+4],%o3
811         srlx    %o0,32,%o1
812         subccc  %o0,%o2,%o2
813         add     $rp,%o7,%g1
814         subccc  %o1,%o3,%o3
815         st      %o2,[%g1+0]
816         add     %o7,8,%o7
817         brnz,pt %o7,.Lsub
818         st      %o3,[%g1+4]
819         subc    $carry,0,%g4
820         sub     %g0,$num,%o7            ! n=-num
821         ba      .Lcopy
822         nop
823
824 .align  32
825 .Lcopy:
826         ldx     [$tp+%o7],%o0
827         add     $rp,%o7,%g1
828         ld      [%g1+0],%o2
829         ld      [%g1+4],%o3
830         stx     %g0,[$tp+%o7]
831         and     %o0,%g4,%o0
832         srlx    %o0,32,%o1
833         andn    %o2,%g4,%o2
834         andn    %o3,%g4,%o3
835         or      %o2,%o0,%o0
836         or      %o3,%o1,%o1
837         st      %o0,[%g1+0]
838         add     %o7,8,%o7
839         brnz,pt %o7,.Lcopy
840         st      %o1,[%g1+4]
841         sub     %g0,$num,%o7            ! n=-num
842
843 .Lzap:
844         stx     %g0,[$ap_l+%o7]
845         stx     %g0,[$ap_h+%o7]
846         stx     %g0,[$np_l+%o7]
847         stx     %g0,[$np_h+%o7]
848         add     %o7,8,%o7
849         brnz,pt %o7,.Lzap
850         nop
851
852         ldx     [%sp+$bias+$frame+48],%o7
853         wr      %g0,%o7,%asi            ! restore %asi
854
855         mov     1,%i0
856 .Lret:
857         ret
858         restore
859 .type   $fname,#function
860 .size   $fname,(.-$fname)
861 .asciz  "Montgomery Multipltication for UltraSPARC, CRYPTOGAMS by <appro\@openssl.org>"
862 .align  32
863 ___
864
865 $code =~ s/\`([^\`]*)\`/eval($1)/gem;
866
867 # Below substitution makes it possible to compile without demanding
868 # VIS extensions on command line, e.g. -xarch=v9 vs. -xarch=v9a. I
869 # dare to do this, because VIS capability is detected at run-time now
870 # and this routine is not called on CPU not capable to execute it. Do
871 # note that fzeros is not the only VIS dependency! Another dependency
872 # is implicit and is just _a_ numerical value loaded to %asi register,
873 # which assembler can't recognize as VIS specific...
874 $code =~ s/fzeros\s+%f([0-9]+)/
875            sprintf(".word\t0x%x\t! fzeros %%f%d",0x81b00c20|($1<<25),$1)
876           /gem;
877
878 print $code;
879 # flush
880 close STDOUT;