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