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