s390x assembler pack.
[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
132         cmp     $num,4
133         bl,a,pn %icc,.Lret
134         clr     %i0
135         andcc   $num,1,%g0              ! $num has to be even...
136         bnz,a,pn %icc,.Lret
137         clr     %i0                     ! signal "unsupported input value"
138
139         srl     $num,1,$num
140         sethi   %hi(0xffff),$mask
141         ld      [%i4+0],$n0             ! $n0 reassigned, remember?
142         or      $mask,%lo(0xffff),$mask
143         ld      [%i4+4],%o0
144         sllx    %o0,32,%o0
145         or      %o0,$n0,$n0             ! $n0=n0[1].n0[0]
146
147         sll     $num,3,$num             ! num*=8
148
149         add     %sp,$bias,%o0           ! real top of stack
150         sll     $num,2,%o1
151         add     %o1,$num,%o1            ! %o1=num*5
152         sub     %o0,%o1,%o0
153         and     %o0,-2048,%o0           ! optimize TLB utilization
154         sub     %o0,$bias,%sp           ! alloca(5*num*8)
155
156         rd      %asi,%o7                ! save %asi
157         add     %sp,$bias+$frame+$locals,$tp
158         add     $tp,$num,$ap_l
159         add     $ap_l,$num,$ap_l        ! [an]p_[lh] point at the vectors' ends !
160         add     $ap_l,$num,$ap_h
161         add     $ap_h,$num,$np_l
162         add     $np_l,$num,$np_h
163
164         wr      %g0,$ASI_FL16_P,%asi    ! setup %asi for 16-bit FP loads
165
166         add     $rp,$num,$rp            ! readjust input pointers to point
167         add     $ap,$num,$ap            ! at the ends too...
168         add     $bp,$num,$bp
169         add     $np,$num,$np
170
171         stx     %o7,[%sp+$bias+$frame+48]       ! save %asi
172 \f
173         sub     %g0,$num,$i             ! i=-num
174         sub     %g0,$num,$j             ! j=-num
175
176         add     $ap,$j,%o3
177         add     $bp,$i,%o4
178
179         ld      [%o3+4],%g1             ! bp[0]
180         ld      [%o3+0],%o0
181         ld      [%o4+4],%g5             ! ap[0]
182         sllx    %g1,32,%g1
183         ld      [%o4+0],%o1
184         sllx    %g5,32,%g5
185         or      %g1,%o0,%o0
186         or      %g5,%o1,%o1
187
188         add     $np,$j,%o5
189
190         mulx    %o1,%o0,%o0             ! ap[0]*bp[0]
191         mulx    $n0,%o0,%o0             ! ap[0]*bp[0]*n0
192         stx     %o0,[%sp+$bias+$frame+0]
193
194         ld      [%o3+0],$alo_   ! load a[j] as pair of 32-bit words
195         fzeros  $alo
196         ld      [%o3+4],$ahi_
197         fzeros  $ahi
198         ld      [%o5+0],$nlo_   ! load n[j] as pair of 32-bit words
199         fzeros  $nlo
200         ld      [%o5+4],$nhi_
201         fzeros  $nhi
202
203         ! transfer b[i] to FPU as 4x16-bit values
204         ldda    [%o4+2]%asi,$ba
205         fxtod   $alo,$alo
206         ldda    [%o4+0]%asi,$bb
207         fxtod   $ahi,$ahi
208         ldda    [%o4+6]%asi,$bc
209         fxtod   $nlo,$nlo
210         ldda    [%o4+4]%asi,$bd
211         fxtod   $nhi,$nhi
212
213         ! transfer ap[0]*b[0]*n0 to FPU as 4x16-bit values
214         ldda    [%sp+$bias+$frame+6]%asi,$na
215         fxtod   $ba,$ba
216         ldda    [%sp+$bias+$frame+4]%asi,$nb
217         fxtod   $bb,$bb
218         ldda    [%sp+$bias+$frame+2]%asi,$nc
219         fxtod   $bc,$bc
220         ldda    [%sp+$bias+$frame+0]%asi,$nd
221         fxtod   $bd,$bd
222
223         std     $alo,[$ap_l+$j]         ! save smashed ap[j] in double format
224         fxtod   $na,$na
225         std     $ahi,[$ap_h+$j]
226         fxtod   $nb,$nb
227         std     $nlo,[$np_l+$j]         ! save smashed np[j] in double format
228         fxtod   $nc,$nc
229         std     $nhi,[$np_h+$j]
230         fxtod   $nd,$nd
231
232                 fmuld   $alo,$ba,$aloa
233                 fmuld   $nlo,$na,$nloa
234                 fmuld   $alo,$bb,$alob
235                 fmuld   $nlo,$nb,$nlob
236                 fmuld   $alo,$bc,$aloc
237         faddd   $aloa,$nloa,$nloa
238                 fmuld   $nlo,$nc,$nloc
239                 fmuld   $alo,$bd,$alod
240         faddd   $alob,$nlob,$nlob
241                 fmuld   $nlo,$nd,$nlod
242                 fmuld   $ahi,$ba,$ahia
243         faddd   $aloc,$nloc,$nloc
244                 fmuld   $nhi,$na,$nhia
245                 fmuld   $ahi,$bb,$ahib
246         faddd   $alod,$nlod,$nlod
247                 fmuld   $nhi,$nb,$nhib
248                 fmuld   $ahi,$bc,$ahic
249         faddd   $ahia,$nhia,$nhia
250                 fmuld   $nhi,$nc,$nhic
251                 fmuld   $ahi,$bd,$ahid
252         faddd   $ahib,$nhib,$nhib
253                 fmuld   $nhi,$nd,$nhid
254
255         faddd   $ahic,$nhic,$dota       ! $nhic
256         faddd   $ahid,$nhid,$dotb       ! $nhid
257
258         faddd   $nloc,$nhia,$nloc
259         faddd   $nlod,$nhib,$nlod
260
261         fdtox   $nloa,$nloa
262         fdtox   $nlob,$nlob
263         fdtox   $nloc,$nloc
264         fdtox   $nlod,$nlod
265
266         std     $nloa,[%sp+$bias+$frame+0]
267         add     $j,8,$j
268         std     $nlob,[%sp+$bias+$frame+8]
269         add     $ap,$j,%o4
270         std     $nloc,[%sp+$bias+$frame+16]
271         add     $np,$j,%o5
272         std     $nlod,[%sp+$bias+$frame+24]
273 \f
274         ld      [%o4+0],$alo_   ! load a[j] as pair of 32-bit words
275         fzeros  $alo
276         ld      [%o4+4],$ahi_
277         fzeros  $ahi
278         ld      [%o5+0],$nlo_   ! load n[j] as pair of 32-bit words
279         fzeros  $nlo
280         ld      [%o5+4],$nhi_
281         fzeros  $nhi
282
283         fxtod   $alo,$alo
284         fxtod   $ahi,$ahi
285         fxtod   $nlo,$nlo
286         fxtod   $nhi,$nhi
287
288         ldx     [%sp+$bias+$frame+0],%o0
289                 fmuld   $alo,$ba,$aloa
290         ldx     [%sp+$bias+$frame+8],%o1
291                 fmuld   $nlo,$na,$nloa
292         ldx     [%sp+$bias+$frame+16],%o2
293                 fmuld   $alo,$bb,$alob
294         ldx     [%sp+$bias+$frame+24],%o3
295                 fmuld   $nlo,$nb,$nlob
296
297         srlx    %o0,16,%o7
298         std     $alo,[$ap_l+$j]         ! save smashed ap[j] in double format
299                 fmuld   $alo,$bc,$aloc
300         add     %o7,%o1,%o1
301         std     $ahi,[$ap_h+$j]
302                 faddd   $aloa,$nloa,$nloa
303                 fmuld   $nlo,$nc,$nloc
304         srlx    %o1,16,%o7
305         std     $nlo,[$np_l+$j]         ! save smashed np[j] in double format
306                 fmuld   $alo,$bd,$alod
307         add     %o7,%o2,%o2
308         std     $nhi,[$np_h+$j]
309                 faddd   $alob,$nlob,$nlob
310                 fmuld   $nlo,$nd,$nlod
311         srlx    %o2,16,%o7
312                 fmuld   $ahi,$ba,$ahia
313         add     %o7,%o3,%o3             ! %o3.%o2[0..15].%o1[0..15].%o0[0..15]
314                 faddd   $aloc,$nloc,$nloc
315                 fmuld   $nhi,$na,$nhia
316         !and    %o0,$mask,%o0
317         !and    %o1,$mask,%o1
318         !and    %o2,$mask,%o2
319         !sllx   %o1,16,%o1
320         !sllx   %o2,32,%o2
321         !sllx   %o3,48,%o7
322         !or     %o1,%o0,%o0
323         !or     %o2,%o0,%o0
324         !or     %o7,%o0,%o0             ! 64-bit result
325         srlx    %o3,16,%g1              ! 34-bit carry
326                 fmuld   $ahi,$bb,$ahib
327
328         faddd   $alod,$nlod,$nlod
329                 fmuld   $nhi,$nb,$nhib
330                 fmuld   $ahi,$bc,$ahic
331         faddd   $ahia,$nhia,$nhia
332                 fmuld   $nhi,$nc,$nhic
333                 fmuld   $ahi,$bd,$ahid
334         faddd   $ahib,$nhib,$nhib
335                 fmuld   $nhi,$nd,$nhid
336
337         faddd   $dota,$nloa,$nloa
338         faddd   $dotb,$nlob,$nlob
339         faddd   $ahic,$nhic,$dota       ! $nhic
340         faddd   $ahid,$nhid,$dotb       ! $nhid
341
342         faddd   $nloc,$nhia,$nloc
343         faddd   $nlod,$nhib,$nlod
344
345         fdtox   $nloa,$nloa
346         fdtox   $nlob,$nlob
347         fdtox   $nloc,$nloc
348         fdtox   $nlod,$nlod
349
350         std     $nloa,[%sp+$bias+$frame+0]
351         std     $nlob,[%sp+$bias+$frame+8]
352         addcc   $j,8,$j
353         std     $nloc,[%sp+$bias+$frame+16]
354         bz,pn   %icc,.L1stskip
355         std     $nlod,[%sp+$bias+$frame+24]
356 \f
357 .align  32,0x1000000
358 .L1st:
359         add     $ap,$j,%o4
360         add     $np,$j,%o5
361         ld      [%o4+0],$alo_   ! load a[j] as pair of 32-bit words
362         fzeros  $alo
363         ld      [%o4+4],$ahi_
364         fzeros  $ahi
365         ld      [%o5+0],$nlo_   ! load n[j] as pair of 32-bit words
366         fzeros  $nlo
367         ld      [%o5+4],$nhi_
368         fzeros  $nhi
369
370         fxtod   $alo,$alo
371         fxtod   $ahi,$ahi
372         fxtod   $nlo,$nlo
373         fxtod   $nhi,$nhi
374
375         ldx     [%sp+$bias+$frame+0],%o0
376                 fmuld   $alo,$ba,$aloa
377         ldx     [%sp+$bias+$frame+8],%o1
378                 fmuld   $nlo,$na,$nloa
379         ldx     [%sp+$bias+$frame+16],%o2
380                 fmuld   $alo,$bb,$alob
381         ldx     [%sp+$bias+$frame+24],%o3
382                 fmuld   $nlo,$nb,$nlob
383
384         srlx    %o0,16,%o7
385         std     $alo,[$ap_l+$j]         ! save smashed ap[j] in double format
386                 fmuld   $alo,$bc,$aloc
387         add     %o7,%o1,%o1
388         std     $ahi,[$ap_h+$j]
389                 faddd   $aloa,$nloa,$nloa
390                 fmuld   $nlo,$nc,$nloc
391         srlx    %o1,16,%o7
392         std     $nlo,[$np_l+$j]         ! save smashed np[j] in double format
393                 fmuld   $alo,$bd,$alod
394         add     %o7,%o2,%o2
395         std     $nhi,[$np_h+$j]
396                 faddd   $alob,$nlob,$nlob
397                 fmuld   $nlo,$nd,$nlod
398         srlx    %o2,16,%o7
399                 fmuld   $ahi,$ba,$ahia
400         add     %o7,%o3,%o3             ! %o3.%o2[0..15].%o1[0..15].%o0[0..15]
401         and     %o0,$mask,%o0
402                 faddd   $aloc,$nloc,$nloc
403                 fmuld   $nhi,$na,$nhia
404         and     %o1,$mask,%o1
405         and     %o2,$mask,%o2
406                 fmuld   $ahi,$bb,$ahib
407         sllx    %o1,16,%o1
408                 faddd   $alod,$nlod,$nlod
409                 fmuld   $nhi,$nb,$nhib
410         sllx    %o2,32,%o2
411                 fmuld   $ahi,$bc,$ahic
412         sllx    %o3,48,%o7
413         or      %o1,%o0,%o0
414                 faddd   $ahia,$nhia,$nhia
415                 fmuld   $nhi,$nc,$nhic
416         or      %o2,%o0,%o0
417                 fmuld   $ahi,$bd,$ahid
418         or      %o7,%o0,%o0             ! 64-bit result
419                 faddd   $ahib,$nhib,$nhib
420                 fmuld   $nhi,$nd,$nhid
421         addcc   %g1,%o0,%o0
422                 faddd   $dota,$nloa,$nloa
423         srlx    %o3,16,%g1              ! 34-bit carry
424                 faddd   $dotb,$nlob,$nlob
425         bcs,a   %xcc,.+8
426         add     %g1,1,%g1
427
428         stx     %o0,[$tp]               ! tp[j-1]=
429
430         faddd   $ahic,$nhic,$dota       ! $nhic
431         faddd   $ahid,$nhid,$dotb       ! $nhid
432
433         faddd   $nloc,$nhia,$nloc
434         faddd   $nlod,$nhib,$nlod
435
436         fdtox   $nloa,$nloa
437         fdtox   $nlob,$nlob
438         fdtox   $nloc,$nloc
439         fdtox   $nlod,$nlod
440
441         std     $nloa,[%sp+$bias+$frame+0]
442         std     $nlob,[%sp+$bias+$frame+8]
443         std     $nloc,[%sp+$bias+$frame+16]
444         std     $nlod,[%sp+$bias+$frame+24]
445
446         addcc   $j,8,$j
447         bnz,pt  %icc,.L1st
448         add     $tp,8,$tp
449 \f
450 .L1stskip:
451         fdtox   $dota,$dota
452         fdtox   $dotb,$dotb
453
454         ldx     [%sp+$bias+$frame+0],%o0
455         ldx     [%sp+$bias+$frame+8],%o1
456         ldx     [%sp+$bias+$frame+16],%o2
457         ldx     [%sp+$bias+$frame+24],%o3
458
459         srlx    %o0,16,%o7
460         std     $dota,[%sp+$bias+$frame+32]
461         add     %o7,%o1,%o1
462         std     $dotb,[%sp+$bias+$frame+40]
463         srlx    %o1,16,%o7
464         add     %o7,%o2,%o2
465         srlx    %o2,16,%o7
466         add     %o7,%o3,%o3             ! %o3.%o2[0..15].%o1[0..15].%o0[0..15]
467         and     %o0,$mask,%o0
468         and     %o1,$mask,%o1
469         and     %o2,$mask,%o2
470         sllx    %o1,16,%o1
471         sllx    %o2,32,%o2
472         sllx    %o3,48,%o7
473         or      %o1,%o0,%o0
474         or      %o2,%o0,%o0
475         or      %o7,%o0,%o0             ! 64-bit result
476         ldx     [%sp+$bias+$frame+32],%o4
477         addcc   %g1,%o0,%o0
478         ldx     [%sp+$bias+$frame+40],%o5
479         srlx    %o3,16,%g1              ! 34-bit carry
480         bcs,a   %xcc,.+8
481         add     %g1,1,%g1
482
483         stx     %o0,[$tp]               ! tp[j-1]=
484         add     $tp,8,$tp
485
486         srlx    %o4,16,%o7
487         add     %o7,%o5,%o5
488         and     %o4,$mask,%o4
489         sllx    %o5,16,%o7
490         or      %o7,%o4,%o4
491         addcc   %g1,%o4,%o4
492         srlx    %o5,48,%g1
493         bcs,a   %xcc,.+8
494         add     %g1,1,%g1
495
496         mov     %g1,$carry
497         stx     %o4,[$tp]               ! tp[num-1]=
498 \f
499         ba      .Louter
500         add     $i,8,$i
501 .align  32
502 .Louter:
503         sub     %g0,$num,$j             ! j=-num
504         add     %sp,$bias+$frame+$locals,$tp
505
506         add     $ap,$j,%o3
507         add     $bp,$i,%o4
508
509         ld      [%o3+4],%g1             ! bp[i]
510         ld      [%o3+0],%o0
511         ld      [%o4+4],%g5             ! ap[0]
512         sllx    %g1,32,%g1
513         ld      [%o4+0],%o1
514         sllx    %g5,32,%g5
515         or      %g1,%o0,%o0
516         or      %g5,%o1,%o1
517
518         ldx     [$tp],%o2               ! tp[0]
519         mulx    %o1,%o0,%o0
520         addcc   %o2,%o0,%o0
521         mulx    $n0,%o0,%o0             ! (ap[0]*bp[i]+t[0])*n0
522         stx     %o0,[%sp+$bias+$frame+0]
523
524         ! transfer b[i] to FPU as 4x16-bit values
525         ldda    [%o4+2]%asi,$ba
526         ldda    [%o4+0]%asi,$bb
527         ldda    [%o4+6]%asi,$bc
528         ldda    [%o4+4]%asi,$bd
529
530         ! transfer (ap[0]*b[i]+t[0])*n0 to FPU as 4x16-bit values
531         ldda    [%sp+$bias+$frame+6]%asi,$na
532         fxtod   $ba,$ba
533         ldda    [%sp+$bias+$frame+4]%asi,$nb
534         fxtod   $bb,$bb
535         ldda    [%sp+$bias+$frame+2]%asi,$nc
536         fxtod   $bc,$bc
537         ldda    [%sp+$bias+$frame+0]%asi,$nd
538         fxtod   $bd,$bd
539         ldd     [$ap_l+$j],$alo         ! load a[j] in double format
540         fxtod   $na,$na
541         ldd     [$ap_h+$j],$ahi
542         fxtod   $nb,$nb
543         ldd     [$np_l+$j],$nlo         ! load n[j] in double format
544         fxtod   $nc,$nc
545         ldd     [$np_h+$j],$nhi
546         fxtod   $nd,$nd
547
548                 fmuld   $alo,$ba,$aloa
549                 fmuld   $nlo,$na,$nloa
550                 fmuld   $alo,$bb,$alob
551                 fmuld   $nlo,$nb,$nlob
552                 fmuld   $alo,$bc,$aloc
553         faddd   $aloa,$nloa,$nloa
554                 fmuld   $nlo,$nc,$nloc
555                 fmuld   $alo,$bd,$alod
556         faddd   $alob,$nlob,$nlob
557                 fmuld   $nlo,$nd,$nlod
558                 fmuld   $ahi,$ba,$ahia
559         faddd   $aloc,$nloc,$nloc
560                 fmuld   $nhi,$na,$nhia
561                 fmuld   $ahi,$bb,$ahib
562         faddd   $alod,$nlod,$nlod
563                 fmuld   $nhi,$nb,$nhib
564                 fmuld   $ahi,$bc,$ahic
565         faddd   $ahia,$nhia,$nhia
566                 fmuld   $nhi,$nc,$nhic
567                 fmuld   $ahi,$bd,$ahid
568         faddd   $ahib,$nhib,$nhib
569                 fmuld   $nhi,$nd,$nhid
570
571         faddd   $ahic,$nhic,$dota       ! $nhic
572         faddd   $ahid,$nhid,$dotb       ! $nhid
573
574         faddd   $nloc,$nhia,$nloc
575         faddd   $nlod,$nhib,$nlod
576
577         fdtox   $nloa,$nloa
578         fdtox   $nlob,$nlob
579         fdtox   $nloc,$nloc
580         fdtox   $nlod,$nlod
581
582         std     $nloa,[%sp+$bias+$frame+0]
583         std     $nlob,[%sp+$bias+$frame+8]
584         std     $nloc,[%sp+$bias+$frame+16]
585         add     $j,8,$j
586         std     $nlod,[%sp+$bias+$frame+24]
587 \f
588         ldd     [$ap_l+$j],$alo         ! load a[j] in double format
589         ldd     [$ap_h+$j],$ahi
590         ldd     [$np_l+$j],$nlo         ! load n[j] in double format
591         ldd     [$np_h+$j],$nhi
592
593                 fmuld   $alo,$ba,$aloa
594                 fmuld   $nlo,$na,$nloa
595                 fmuld   $alo,$bb,$alob
596                 fmuld   $nlo,$nb,$nlob
597                 fmuld   $alo,$bc,$aloc
598         ldx     [%sp+$bias+$frame+0],%o0
599                 faddd   $aloa,$nloa,$nloa
600                 fmuld   $nlo,$nc,$nloc
601         ldx     [%sp+$bias+$frame+8],%o1
602                 fmuld   $alo,$bd,$alod
603         ldx     [%sp+$bias+$frame+16],%o2
604                 faddd   $alob,$nlob,$nlob
605                 fmuld   $nlo,$nd,$nlod
606         ldx     [%sp+$bias+$frame+24],%o3
607                 fmuld   $ahi,$ba,$ahia
608
609         srlx    %o0,16,%o7
610                 faddd   $aloc,$nloc,$nloc
611                 fmuld   $nhi,$na,$nhia
612         add     %o7,%o1,%o1
613                 fmuld   $ahi,$bb,$ahib
614         srlx    %o1,16,%o7
615                 faddd   $alod,$nlod,$nlod
616                 fmuld   $nhi,$nb,$nhib
617         add     %o7,%o2,%o2
618                 fmuld   $ahi,$bc,$ahic
619         srlx    %o2,16,%o7
620                 faddd   $ahia,$nhia,$nhia
621                 fmuld   $nhi,$nc,$nhic
622         add     %o7,%o3,%o3             ! %o3.%o2[0..15].%o1[0..15].%o0[0..15]
623         ! why?
624         and     %o0,$mask,%o0
625                 fmuld   $ahi,$bd,$ahid
626         and     %o1,$mask,%o1
627         and     %o2,$mask,%o2
628                 faddd   $ahib,$nhib,$nhib
629                 fmuld   $nhi,$nd,$nhid
630         sllx    %o1,16,%o1
631                 faddd   $dota,$nloa,$nloa
632         sllx    %o2,32,%o2
633                 faddd   $dotb,$nlob,$nlob
634         sllx    %o3,48,%o7
635         or      %o1,%o0,%o0
636                 faddd   $ahic,$nhic,$dota       ! $nhic
637         or      %o2,%o0,%o0
638                 faddd   $ahid,$nhid,$dotb       ! $nhid
639         or      %o7,%o0,%o0             ! 64-bit result
640         ldx     [$tp],%o7
641                 faddd   $nloc,$nhia,$nloc
642         addcc   %o7,%o0,%o0
643         ! end-of-why?
644                 faddd   $nlod,$nhib,$nlod
645         srlx    %o3,16,%g1              ! 34-bit carry
646                 fdtox   $nloa,$nloa
647         bcs,a   %xcc,.+8
648         add     %g1,1,%g1
649
650         fdtox   $nlob,$nlob
651         fdtox   $nloc,$nloc
652         fdtox   $nlod,$nlod
653
654         std     $nloa,[%sp+$bias+$frame+0]
655         std     $nlob,[%sp+$bias+$frame+8]
656         addcc   $j,8,$j
657         std     $nloc,[%sp+$bias+$frame+16]
658         bz,pn   %icc,.Linnerskip
659         std     $nlod,[%sp+$bias+$frame+24]
660 \f
661         ba      .Linner
662         nop
663 .align  32
664 .Linner:
665         ldd     [$ap_l+$j],$alo         ! load a[j] in double format
666         ldd     [$ap_h+$j],$ahi
667         ldd     [$np_l+$j],$nlo         ! load n[j] in double format
668         ldd     [$np_h+$j],$nhi
669
670                 fmuld   $alo,$ba,$aloa
671                 fmuld   $nlo,$na,$nloa
672                 fmuld   $alo,$bb,$alob
673                 fmuld   $nlo,$nb,$nlob
674                 fmuld   $alo,$bc,$aloc
675         ldx     [%sp+$bias+$frame+0],%o0
676                 faddd   $aloa,$nloa,$nloa
677                 fmuld   $nlo,$nc,$nloc
678         ldx     [%sp+$bias+$frame+8],%o1
679                 fmuld   $alo,$bd,$alod
680         ldx     [%sp+$bias+$frame+16],%o2
681                 faddd   $alob,$nlob,$nlob
682                 fmuld   $nlo,$nd,$nlod
683         ldx     [%sp+$bias+$frame+24],%o3
684                 fmuld   $ahi,$ba,$ahia
685
686         srlx    %o0,16,%o7
687                 faddd   $aloc,$nloc,$nloc
688                 fmuld   $nhi,$na,$nhia
689         add     %o7,%o1,%o1
690                 fmuld   $ahi,$bb,$ahib
691         srlx    %o1,16,%o7
692                 faddd   $alod,$nlod,$nlod
693                 fmuld   $nhi,$nb,$nhib
694         add     %o7,%o2,%o2
695                 fmuld   $ahi,$bc,$ahic
696         srlx    %o2,16,%o7
697                 faddd   $ahia,$nhia,$nhia
698                 fmuld   $nhi,$nc,$nhic
699         add     %o7,%o3,%o3             ! %o3.%o2[0..15].%o1[0..15].%o0[0..15]
700         and     %o0,$mask,%o0
701                 fmuld   $ahi,$bd,$ahid
702         and     %o1,$mask,%o1
703         and     %o2,$mask,%o2
704                 faddd   $ahib,$nhib,$nhib
705                 fmuld   $nhi,$nd,$nhid
706         sllx    %o1,16,%o1
707                 faddd   $dota,$nloa,$nloa
708         sllx    %o2,32,%o2
709                 faddd   $dotb,$nlob,$nlob
710         sllx    %o3,48,%o7
711         or      %o1,%o0,%o0
712                 faddd   $ahic,$nhic,$dota       ! $nhic
713         or      %o2,%o0,%o0
714                 faddd   $ahid,$nhid,$dotb       ! $nhid
715         or      %o7,%o0,%o0             ! 64-bit result
716                 faddd   $nloc,$nhia,$nloc
717         addcc   %g1,%o0,%o0
718         ldx     [$tp+8],%o7             ! tp[j]
719                 faddd   $nlod,$nhib,$nlod
720         srlx    %o3,16,%g1              ! 34-bit carry
721                 fdtox   $nloa,$nloa
722         bcs,a   %xcc,.+8
723         add     %g1,1,%g1
724                 fdtox   $nlob,$nlob
725         addcc   %o7,%o0,%o0
726                 fdtox   $nloc,$nloc
727         bcs,a   %xcc,.+8
728         add     %g1,1,%g1
729
730         stx     %o0,[$tp]               ! tp[j-1]
731                 fdtox   $nlod,$nlod
732
733         std     $nloa,[%sp+$bias+$frame+0]
734         std     $nlob,[%sp+$bias+$frame+8]
735         std     $nloc,[%sp+$bias+$frame+16]
736         addcc   $j,8,$j
737         std     $nlod,[%sp+$bias+$frame+24]
738         bnz,pt  %icc,.Linner
739         add     $tp,8,$tp
740 \f
741 .Linnerskip:
742         fdtox   $dota,$dota
743         fdtox   $dotb,$dotb
744
745         ldx     [%sp+$bias+$frame+0],%o0
746         ldx     [%sp+$bias+$frame+8],%o1
747         ldx     [%sp+$bias+$frame+16],%o2
748         ldx     [%sp+$bias+$frame+24],%o3
749
750         srlx    %o0,16,%o7
751         std     $dota,[%sp+$bias+$frame+32]
752         add     %o7,%o1,%o1
753         std     $dotb,[%sp+$bias+$frame+40]
754         srlx    %o1,16,%o7
755         add     %o7,%o2,%o2
756         srlx    %o2,16,%o7
757         add     %o7,%o3,%o3             ! %o3.%o2[0..15].%o1[0..15].%o0[0..15]
758         and     %o0,$mask,%o0
759         and     %o1,$mask,%o1
760         and     %o2,$mask,%o2
761         sllx    %o1,16,%o1
762         sllx    %o2,32,%o2
763         sllx    %o3,48,%o7
764         or      %o1,%o0,%o0
765         or      %o2,%o0,%o0
766         ldx     [%sp+$bias+$frame+32],%o4
767         or      %o7,%o0,%o0             ! 64-bit result
768         ldx     [%sp+$bias+$frame+40],%o5
769         addcc   %g1,%o0,%o0
770         ldx     [$tp+8],%o7             ! tp[j]
771         srlx    %o3,16,%g1              ! 34-bit carry
772         bcs,a   %xcc,.+8
773         add     %g1,1,%g1
774
775         addcc   %o7,%o0,%o0
776         bcs,a   %xcc,.+8
777         add     %g1,1,%g1
778
779         stx     %o0,[$tp]               ! tp[j-1]
780         add     $tp,8,$tp
781
782         srlx    %o4,16,%o7
783         add     %o7,%o5,%o5
784         and     %o4,$mask,%o4
785         sllx    %o5,16,%o7
786         or      %o7,%o4,%o4
787         addcc   %g1,%o4,%o4
788         srlx    %o5,48,%g1
789         bcs,a   %xcc,.+8
790         add     %g1,1,%g1
791
792         addcc   $carry,%o4,%o4
793         stx     %o4,[$tp]               ! tp[num-1]
794         mov     %g1,$carry
795         bcs,a   %xcc,.+8
796         add     $carry,1,$carry
797
798         addcc   $i,8,$i
799         bnz     %icc,.Louter
800         nop
801 \f
802         sub     %g0,$num,%o7            ! n=-num
803         cmp     $carry,0                ! clears %icc.c
804         bne,pn  %icc,.Lsub
805         add     $tp,8,$tp               ! adjust tp to point at the end
806
807         ld      [$tp-8],%o0
808         ld      [$np-4],%o1
809         cmp     %o0,%o1                 ! compare topmost words
810         bcs,pt  %icc,.Lcopy             ! %icc.c is clean if not taken
811         nop
812
813 .align  32,0x1000000
814 .Lsub:
815         ldx     [$tp+%o7],%o0
816         add     $np,%o7,%g1
817         ld      [%g1+0],%o2
818         ld      [%g1+4],%o3
819         srlx    %o0,32,%o1
820         subccc  %o0,%o2,%o2
821         add     $rp,%o7,%g1
822         subccc  %o1,%o3,%o3
823         st      %o2,[%g1+0]
824         add     %o7,8,%o7
825         brnz,pt %o7,.Lsub
826         st      %o3,[%g1+4]
827         subccc  $carry,0,$carry
828         bcc,pt  %icc,.Lzap
829         sub     %g0,$num,%o7            ! n=-num
830
831 .align  16,0x1000000
832 .Lcopy:
833         ldx     [$tp+%o7],%o0
834         srlx    %o0,32,%o1
835         add     $rp,%o7,%g1
836         st      %o0,[%g1+0]
837         add     %o7,8,%o7
838         brnz,pt %o7,.Lcopy
839         st      %o1,[%g1+4]
840         sub     %g0,$num,%o7            ! n=-num
841
842 .align  32
843 .Lzap:
844         stx     %g0,[$tp+%o7]
845         stx     %g0,[$ap_l+%o7]
846         stx     %g0,[$ap_h+%o7]
847         stx     %g0,[$np_l+%o7]
848         stx     %g0,[$np_h+%o7]
849         add     %o7,8,%o7
850         brnz,pt %o7,.Lzap
851         nop
852
853         ldx     [%sp+$bias+$frame+48],%o7
854         wr      %g0,%o7,%asi            ! restore %asi
855
856         mov     1,%i0
857 .Lret:
858         ret
859         restore
860 .type   $fname,#function
861 .size   $fname,(.-$fname)
862 .asciz  "Montgomery Multipltication for UltraSPARC, CRYPTOGAMS by <appro\@openssl.org>"
863 ___
864
865 $code =~ s/\`([^\`]*)\`/eval($1)/gem;
866
867 # Below substitution makes it possible to compile without demanding
868 # VIS extentions 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;