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 # ====================================================================
10 # On PA-7100LC this module performs ~90-50% better, less for longer
11 # keys, than code generated by gcc 3.2 for PA-RISC 1.1. Latter means
12 # that compiler utilized xmpyu instruction to perform 32x32=64-bit
13 # multiplication, which in turn means that "baseline" performance was
14 # optimal in respect to instruction set capabilities. Fair comparison
15 # with vendor compiler is problematic, because OpenSSL doesn't define
16 # BN_LLONG [presumably] for historical reasons, which drives compiler
17 # toward 4 times 16x16=32-bit multiplicatons [plus complementary
18 # shifts and additions] instead. This means that you should observe
19 # several times improvement over code generated by vendor compiler
20 # for PA-RISC 1.1, but the "baseline" is far from optimal. The actual
21 # improvement coefficient was never collected on PA-7100LC, or any
22 # other 1.1 CPU, because I don't have access to such machine with
23 # vendor compiler. But to give you a taste, PA-RISC 1.1 code-path
24 # reportedly outperformed code generated by cc +DA1.1 +O3 by factor
27 # On PA-RISC 2.0 it has to compete with pa-risc2[W].s, which is
28 # reportedly ~2x faster than vendor compiler generated code [see
29 # commentary in assembler source code]. Here comes a catch. Execution
30 # core of this implementation is actually 32-bit one, in the sense
31 # that it expects arrays of 32-bit BN_LONG values as input. But
32 # pa-risc2[W].s operates on arrays of 64-bit BN_LONGs... How do they
33 # interoperate then? Simple. This module picks halves of 64-bit
34 # values in reverse order. But can it compete with "pure" 64-bit code
35 # such as pa-risc2[W].s then? Well, the thing is that 32x32=64-bit
36 # multiplication is the best even PA-RISC 2.0 can do, i.e. there is
37 # no "wider" multiplication like on most other 64-bit platforms.
38 # This means that even being effectively 32-bit, this implementation
39 # performs the same computational task in same amount of arithmetic
40 # operations, most notably multiplications. It requires more memory
41 # references, most notably to tp[num], but this doesn't seem to
42 # exhaust memory port capacity. In other words this implementation,
43 # or more specifically its PA-RISC 2.0 code-path, competes with
44 # pa-risc2W.s on virtually same terms.
46 # In case it wasn't clear. The module has two distinct code-paths:
47 # PA-RISC 1.1 and PA-RISC 2.0 ones. Latter features carry-free 64-bit
48 # additions and 64-bit integer loads, not to mention specific
49 # instruction scheduling. In 32-bit build module imposes couple of
50 # limitations: vector lengths has to be even and vector addresses has
51 # to be 64-bit aligned. Normally neither is a problem: most common
52 # key lengths are even and vectors are commonly malloc-ed, which
53 # ensures 64-bit alignment.
55 # Special thanks to polarhome.com for providing HP-UX account.
57 $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
62 open STDOUT,">$output";
64 if ($flavour =~ /64/) {
75 $LEVEL ="1.1"; #$LEVEL.="\n\t.ALLOW\t2.0";
84 if (open CONF,"<${dir}../../opensslconf.h") {
86 if (m/#\s*define\s+SIXTY_FOUR_BIT/) {
96 $FRAME=8*$SIZE_T+$FRAME_MARKER; # 8 saved regs + frame marker
97 # [+ argument transfer]
98 $LOCALS=$FRAME-$FRAME_MARKER;
99 $FRAME+=32; # local variables
109 $n0="%r22"; # passed through stack in 32-bit
110 $num="%r21"; # passed through stack in 32-bit
123 $xfer=$n0; # accomodates [-16..15] offset in fld[dw]s
125 $fm0="%fr4"; $fti=$fm0;
128 $fai="%fr6"; $fab0="%fr7"; $fab1="%fr8";
129 $fni="%fr9"; $fnm0="%fr10"; $fnm1="%fr11";
134 .SUBSPA \$CODE\$,QUAD=0,ALIGN=8,ACCESS=0x2C,CODE_ONLY
136 .EXPORT bn_mul_mont,ENTRY,ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR
140 .CALLINFO FRAME=`$FRAME-8*$SIZE_T`,NO_CALLS,SAVE_RP,SAVE_SP,ENTRY_GR=6
142 $PUSH %r2,-$SAVED_RP(%sp) ; standard prologue
143 $PUSHMA %r3,$FRAME(%sp)
144 $PUSH %r4,`-$FRAME+1*$SIZE_T`(%sp)
145 $PUSH %r5,`-$FRAME+2*$SIZE_T`(%sp)
146 $PUSH %r6,`-$FRAME+3*$SIZE_T`(%sp)
147 $PUSH %r7,`-$FRAME+4*$SIZE_T`(%sp)
148 $PUSH %r8,`-$FRAME+5*$SIZE_T`(%sp)
149 $PUSH %r9,`-$FRAME+6*$SIZE_T`(%sp)
150 $PUSH %r10,`-$FRAME+7*$SIZE_T`(%sp)
153 $code.=<<___ if ($SIZE_T==4);
154 ldw `-$FRAME_MARKER-4`($fp),$n0
155 ldw `-$FRAME_MARKER-8`($fp),$num
159 $code.=<<___ if ($BN_SZ==4);
160 comiclr,<= 6,$num,%r0 ; are vectors long enough?
162 ldi 0,%r28 ; signal "unhandled"
163 add,ev %r0,$num,$num ; is $num even?
167 extru,= $ti1,31,3,%r0 ; are ap and np 64-bit aligned?
173 fldws,ma 4($bp),${fbi} ; bp[0]
175 $code.=<<___ if ($BN_SZ==8);
176 comib,> 3,$num,L\$abort ; are vectors long enough?
177 ldi 0,%r28 ; signal "unhandled"
178 addl $num,$num,$num ; I operate on 32-bit values
180 fldws 4($n0),${fn0} ; only low part of n0
181 fldws 4($bp),${fbi} ; bp[0] in flipped word order
184 fldds 0($ap),${fai} ; ap[0,1]
185 fldds 0($np),${fni} ; np[0,1]
187 sh2addl $num,%r0,$arrsz
189 ldo 36($arrsz),$hi1 ; space for tp[num+1]
190 andcm $hi1,$hi0,$hi1 ; align
192 $PUSH $fp,-$SIZE_T(%sp)
194 ldo `$LOCALS+16`($fp),$xfer
195 ldo `$LOCALS+32+4`($fp),$tp
197 xmpyu ${fai}L,${fbi},${fab0} ; ap[0]*bp[0]
198 xmpyu ${fai}R,${fbi},${fab1} ; ap[1]*bp[0]
199 xmpyu ${fn0},${fab0}R,${fm0}
201 addl $arrsz,$ap,$ap ; point at the end
203 subi 0,$arrsz,$idx ; j=0
204 ldo 8($idx),$idx ; j++++
206 xmpyu ${fni}L,${fm0}R,${fnm0} ; np[0]*m
207 xmpyu ${fni}R,${fm0}R,${fnm1} ; np[1]*m
208 fstds ${fab0},-16($xfer)
209 fstds ${fnm0},-8($xfer)
210 fstds ${fab1},0($xfer)
211 fstds ${fnm1},8($xfer)
212 flddx $idx($ap),${fai} ; ap[2,3]
213 flddx $idx($np),${fni} ; np[2,3]
215 $code.=<<___ if ($BN_SZ==4);
216 mtctl $hi0,%cr11 ; $hi0 still holds 31
217 extrd,u,*= $hi0,%sar,1,$hi0 ; executes on PA-RISC 1.0
221 $code.=<<___; # PA-RISC 2.0 code-path
225 extrd,u $ab0,31,32,$hi0
226 extrd,u $ab0,63,32,$ab0
227 ldo 8($idx),$idx ; j++++
228 addl $ab0,$nm0,$nm0 ; low part is discarded
229 extrd,u $nm0,31,32,$hi1
233 xmpyu ${fai}L,${fbi},${fab0} ; ap[j]*bp[0]
234 xmpyu ${fni}L,${fm0}R,${fnm0} ; np[j]*m
236 fstds ${fab0},-16($xfer)
237 xmpyu ${fai}R,${fbi},${fab1} ; ap[j+1]*bp[0]
238 xmpyu ${fni}R,${fm0}R,${fnm1} ; np[j+1]*m
239 fstds ${fnm0},-8($xfer)
241 fstds ${fab1},0($xfer)
242 extrd,u $ab1,31,32,$hi0
243 fstds ${fnm1},8($xfer)
244 extrd,u $ab1,63,32,$ab1
249 extrd,u $nm1,31,32,$hi1
251 flddx $idx($ap),${fai} ; ap[j,j+1]
253 flddx $idx($np),${fni} ; np[j,j+1]
254 extrd,u $ab0,31,32,$hi0
255 stw $nm1,-4($tp) ; tp[j-1]
256 extrd,u $ab0,63,32,$ab0
260 stw,ma $nm0,8($tp) ; tp[j-1]
261 addib,<> 8,$idx,L\$1st ; j++++
262 extrd,u $nm0,31,32,$hi1
264 xmpyu ${fai}L,${fbi},${fab0} ; ap[j]*bp[0]
265 xmpyu ${fni}L,${fm0}R,${fnm0} ; np[j]*m
267 fstds ${fab0},-16($xfer)
268 xmpyu ${fai}R,${fbi},${fab1} ; ap[j]*bp[0]
269 xmpyu ${fni}R,${fm0}R,${fnm1} ; np[j]*m
270 fstds ${fnm0},-8($xfer)
272 fstds ${fab1},0($xfer)
273 extrd,u $ab1,31,32,$hi0
274 fstds ${fnm1},8($xfer)
275 extrd,u $ab1,63,32,$ab1
280 extrd,u $nm1,31,32,$hi1
283 extrd,u $ab0,31,32,$hi0
284 stw $nm1,-4($tp) ; tp[j-1]
285 extrd,u $ab0,63,32,$ab0
290 extrd,u $nm0,31,32,$hi1
291 stw,ma $nm0,8($tp) ; tp[j-1]
293 ldo -1($num),$num ; i--
294 subi 0,$arrsz,$idx ; j=0
296 $code.=<<___ if ($BN_SZ==4);
297 fldws,ma 4($bp),${fbi} ; bp[1]
299 $code.=<<___ if ($BN_SZ==8);
300 fldws 0($bp),${fbi} ; bp[1] in flipped word order
303 flddx $idx($ap),${fai} ; ap[0,1]
304 flddx $idx($np),${fni} ; np[0,1]
305 fldws 8($xfer),${fti}R ; tp[0]
307 extrd,u $ab1,31,32,$hi0
308 extrd,u $ab1,63,32,$ab1
309 ldo 8($idx),$idx ; j++++
310 xmpyu ${fai}L,${fbi},${fab0} ; ap[0]*bp[1]
311 xmpyu ${fai}R,${fbi},${fab1} ; ap[1]*bp[1]
314 extrd,u $nm1,31,32,$hi1
315 fstws,mb ${fab0}L,-8($xfer) ; save high part
316 stw $nm1,-4($tp) ; tp[j-1]
318 fcpy,sgl %fr0,${fti}L ; zero high part
319 fcpy,sgl %fr0,${fab0}L
321 extrd,u $hi0,31,32,$hi1
322 fcnvxf,dbl,dbl ${fti},${fti} ; 32-bit unsigned int -> double
323 fcnvxf,dbl,dbl ${fab0},${fab0}
327 fadd,dbl ${fti},${fab0},${fab0} ; add tp[0]
328 fcnvfx,dbl,dbl ${fab0},${fab0} ; double -> 33-bit unsigned int
329 xmpyu ${fn0},${fab0}R,${fm0}
330 ldo `$LOCALS+32+4`($fp),$tp
332 xmpyu ${fni}L,${fm0}R,${fnm0} ; np[0]*m
333 xmpyu ${fni}R,${fm0}R,${fnm1} ; np[1]*m
334 fstds ${fab0},-16($xfer) ; 33-bit value
335 fstds ${fnm0},-8($xfer)
336 flddx $idx($ap),${fai} ; ap[2]
337 flddx $idx($np),${fni} ; np[2]
338 ldo 8($idx),$idx ; j++++
339 ldd -16($xfer),$ab0 ; 33-bit value
341 ldw 0($xfer),$hi0 ; high part
343 extrd,u $ab0,31,32,$ti0 ; carry bit
344 extrd,u $ab0,63,32,$ab0
345 fstds ${fab1},0($xfer)
346 addl $ti0,$hi0,$hi0 ; account carry bit
347 fstds ${fnm1},8($xfer)
348 addl $ab0,$nm0,$nm0 ; low part is discarded
349 ldw 0($tp),$ti1 ; tp[1]
350 extrd,u $nm0,31,32,$hi1
354 xmpyu ${fai}L,${fbi},${fab0} ; ap[j]*bp[i]
355 xmpyu ${fni}L,${fm0}R,${fnm0} ; np[j]*m
357 fstds ${fab0},-16($xfer)
358 xmpyu ${fai}R,${fbi},${fab1} ; ap[j+1]*bp[i]
359 xmpyu ${fni}R,${fm0}R,${fnm1} ; np[j+1]*m
360 fstds ${fnm0},-8($xfer)
361 ldw 4($tp),$ti0 ; tp[j]
363 fstds ${fab1},0($xfer)
365 extrd,u $ab1,31,32,$hi0
366 fstds ${fnm1},8($xfer)
367 extrd,u $ab1,63,32,$ab1
372 extrd,u $nm1,31,32,$hi1
374 flddx $idx($ap),${fai} ; ap[j,j+1]
376 flddx $idx($np),${fni} ; np[j,j+1]
378 stw $nm1,-4($tp) ; tp[j-1]
379 extrd,u $ab0,31,32,$hi0
380 ldw 8($tp),$ti1 ; tp[j]
381 extrd,u $ab0,63,32,$ab0
385 stw,ma $nm0,8($tp) ; tp[j-1]
386 addib,<> 8,$idx,L\$inner ; j++++
387 extrd,u $nm0,31,32,$hi1
389 xmpyu ${fai}L,${fbi},${fab0} ; ap[j]*bp[i]
390 xmpyu ${fni}L,${fm0}R,${fnm0} ; np[j]*m
392 fstds ${fab0},-16($xfer)
393 xmpyu ${fai}R,${fbi},${fab1} ; ap[j]*bp[i]
394 xmpyu ${fni}R,${fm0}R,${fnm1} ; np[j]*m
395 fstds ${fnm0},-8($xfer)
396 ldw 4($tp),$ti0 ; tp[j]
398 fstds ${fab1},0($xfer)
400 extrd,u $ab1,31,32,$hi0
401 fstds ${fnm1},8($xfer)
402 extrd,u $ab1,63,32,$ab1
407 extrd,u $nm1,31,32,$hi1
411 stw $nm1,-4($tp) ; tp[j-1]
412 extrd,u $ab0,31,32,$hi0
413 ldw 8($tp),$ti1 ; tp[j]
414 extrd,u $ab0,63,32,$ab0
419 extrd,u $nm0,31,32,$hi1
420 stw,ma $nm0,8($tp) ; tp[j-1]
422 addib,= -1,$num,L\$outerdone ; i--
423 subi 0,$arrsz,$idx ; j=0
425 $code.=<<___ if ($BN_SZ==4);
426 fldws,ma 4($bp),${fbi} ; bp[i]
428 $code.=<<___ if ($BN_SZ==8);
429 ldi 12,$ti0 ; bp[i] in flipped word order
430 addl,ev %r0,$num,$num
436 flddx $idx($ap),${fai} ; ap[0]
438 flddx $idx($np),${fni} ; np[0]
439 fldws 8($xfer),${fti}R ; tp[0]
441 extrd,u $ab1,31,32,$hi0
442 extrd,u $ab1,63,32,$ab1
444 ldo 8($idx),$idx ; j++++
445 xmpyu ${fai}L,${fbi},${fab0} ; ap[0]*bp[i]
446 xmpyu ${fai}R,${fbi},${fab1} ; ap[1]*bp[i]
447 ldw 4($tp),$ti0 ; tp[j]
450 fstws,mb ${fab0}L,-8($xfer) ; save high part
452 extrd,u $nm1,31,32,$hi1
453 fcpy,sgl %fr0,${fti}L ; zero high part
454 fcpy,sgl %fr0,${fab0}L
455 stw $nm1,-4($tp) ; tp[j-1]
457 fcnvxf,dbl,dbl ${fti},${fti} ; 32-bit unsigned int -> double
458 fcnvxf,dbl,dbl ${fab0},${fab0}
460 fadd,dbl ${fti},${fab0},${fab0} ; add tp[0]
462 extrd,u $hi0,31,32,$hi1
463 fcnvfx,dbl,dbl ${fab0},${fab0} ; double -> 33-bit unsigned int
466 xmpyu ${fn0},${fab0}R,${fm0}
469 ldo `$LOCALS+32+4`($fp),$tp
474 extrd,u $ab1,31,32,$hi0
475 extrd,u $ab1,63,32,$ab1
477 ldw 4($tp),$ti0 ; tp[j]
481 extrd,u $nm1,31,32,$hi1
482 stw $nm1,-4($tp) ; tp[j-1]
486 extrd,u $hi0,31,32,$hi1
490 ldo `$LOCALS+32`($fp),$tp
491 sub %r0,%r0,%r0 ; clear borrow
493 $code.=<<___ if ($BN_SZ==4);
495 extru,= $rp,31,3,%r0 ; is rp 64-bit aligned?
502 addib,<> 4,$idx,L\$sub
508 $code.=<<___ if ($BN_SZ==8);
512 shrpd $ti0,$ti0,32,$ti0 ; flip word order
513 std $ti0,-8($tp) ; save flipped value
514 sub,db $ti0,$hi0,$hi1
516 addib,<> 8,$idx,L\$sub
519 extrd,u $ti0,31,32,$ti0 ; carry in flipped word order
528 sub $rp,$arrsz,$rp ; rewind rp
530 ldo `$LOCALS+32`($fp),$tp
534 addib,<> 8,$idx,.-8 ; L\$copy
538 if ($BN_SZ==4) { # PA-RISC 1.1 code-path
557 ldo 8($idx),$idx ; j++++
558 add $ablo,$nmlo0,$nmlo0 ; discarded
565 xmpyu ${fai}L,${fbi},${fab0} ; ap[j]*bp[0]
567 xmpyu ${fni}L,${fm0}R,${fnm0} ; np[j]*m
569 xmpyu ${fai}R,${fbi},${fab1} ; ap[j+1]*bp[0]
570 fstds ${fab0},-16($xfer)
571 xmpyu ${fni}R,${fm0}R,${fnm1} ; np[j+1]*m
572 fstds ${fnm0},-8($xfer)
574 fstds ${fab1},0($xfer)
576 fstds ${fnm1},8($xfer)
577 add $ablo,$nmlo1,$nmlo1
579 addc %r0,$nmhi1,$nmhi1
581 add $hi1,$nmlo1,$nmlo1
587 flddx $idx($ap),${fai} ; ap[j,j+1]
589 flddx $idx($np),${fni} ; np[j,j+1]
590 add $ablo,$nmlo0,$nmlo0
591 stw $nmlo1,-4($tp) ; tp[j-1]
592 addc %r0,$nmhi0,$nmhi0
594 add $hi1,$nmlo0,$nmlo0
596 stws,ma $nmlo0,8($tp) ; tp[j-1]
597 addib,<> 8,$idx,L\$1st_pa11 ; j++++
600 xmpyu ${fai}L,${fbi},${fab0} ; ap[j]*bp[0]
602 xmpyu ${fni}L,${fm0}R,${fnm0} ; np[j]*m
604 xmpyu ${fai}R,${fbi},${fab1} ; ap[j]*bp[0]
605 xmpyu ${fni}R,${fm0}R,${fnm1} ; np[j]*m
606 fstds ${fab0},-16($xfer)
607 fstds ${fnm0},-8($xfer)
609 fstds ${fab1},0($xfer)
611 fstds ${fnm1},8($xfer)
612 add $ablo,$nmlo1,$nmlo1
614 addc %r0,$nmhi1,$nmhi1
616 add $hi1,$nmlo1,$nmlo1
622 stw $nmlo1,-4($tp) ; tp[j-1]
625 add $ablo,$nmlo0,$nmlo0
627 addc %r0,$nmhi0,$nmhi0
628 ldws,mb 8($xfer),$nmhi1
629 add $hi1,$nmlo0,$nmlo0
632 stws,ma $nmlo0,8($tp) ; tp[j-1]
634 ldo -1($num),$num ; i--
635 subi 0,$arrsz,$idx ; j=0
637 fldws,ma 4($bp),${fbi} ; bp[1]
638 flddx $idx($ap),${fai} ; ap[0,1]
639 flddx $idx($np),${fni} ; np[0,1]
640 fldws 8($xfer),${fti}R ; tp[0]
643 ldo 8($idx),$idx ; j++++
644 xmpyu ${fai}L,${fbi},${fab0} ; ap[0]*bp[1]
645 xmpyu ${fai}R,${fbi},${fab1} ; ap[1]*bp[1]
646 add $hi1,$nmlo1,$nmlo1
647 addc %r0,$nmhi1,$nmhi1
648 add $ablo,$nmlo1,$nmlo1
650 fstws,mb ${fab0}L,-8($xfer) ; save high part
651 stw $nmlo1,-4($tp) ; tp[j-1]
653 fcpy,sgl %fr0,${fti}L ; zero high part
654 fcpy,sgl %fr0,${fab0}L
657 fcnvxf,dbl,dbl ${fti},${fti} ; 32-bit unsigned int -> double
658 fcnvxf,dbl,dbl ${fab0},${fab0}
662 fadd,dbl ${fti},${fab0},${fab0} ; add tp[0]
663 fcnvfx,dbl,dbl ${fab0},${fab0} ; double -> 33-bit unsigned int
664 xmpyu ${fn0},${fab0}R,${fm0}
665 ldo `$LOCALS+32+4`($fp),$tp
667 xmpyu ${fni}L,${fm0}R,${fnm0} ; np[0]*m
668 xmpyu ${fni}R,${fm0}R,${fnm1} ; np[1]*m
669 fstds ${fab0},-16($xfer) ; 33-bit value
670 fstds ${fnm0},-8($xfer)
671 flddx $idx($ap),${fai} ; ap[2,3]
672 flddx $idx($np),${fni} ; np[2,3]
673 ldw -16($xfer),$abhi ; carry bit actually
674 ldo 8($idx),$idx ; j++++
678 ldw 0($xfer),$hi0 ; high part
680 fstds ${fab1},0($xfer)
681 addl $abhi,$hi0,$hi0 ; account carry bit
682 fstds ${fnm1},8($xfer)
683 add $ablo,$nmlo0,$nmlo0 ; discarded
684 ldw 0($tp),$ti1 ; tp[1]
690 xmpyu ${fai}L,${fbi},${fab0} ; ap[j]*bp[i]
692 xmpyu ${fni}L,${fm0}R,${fnm0} ; np[j]*m
694 xmpyu ${fai}R,${fbi},${fab1} ; ap[j+1]*bp[i]
695 fstds ${fab0},-16($xfer)
696 xmpyu ${fni}R,${fm0}R,${fnm1} ; np[j+1]*m
697 fstds ${fnm0},-8($xfer)
699 ldw 4($tp),$ti0 ; tp[j]
701 fstds ${fab1},0($xfer)
703 fstds ${fnm1},8($xfer)
706 add $ablo,$nmlo1,$nmlo1
708 addc %r0,$nmhi1,$nmhi1
710 add $hi1,$nmlo1,$nmlo1
714 flddx $idx($ap),${fai} ; ap[j,j+1]
715 addl,nuv $hi0,$ablo,$ablo
717 flddx $idx($np),${fni} ; np[j,j+1]
719 stw $nmlo1,-4($tp) ; tp[j-1]
721 ldw 8($tp),$ti1 ; tp[j]
722 addl,nuv $ablo,$nmlo0,$nmlo0
725 add $hi1,$nmlo0,$nmlo0
727 stws,ma $nmlo0,8($tp) ; tp[j-1]
728 addib,<> 8,$idx,L\$inner_pa11 ; j++++
731 xmpyu ${fai}L,${fbi},${fab0} ; ap[j]*bp[i]
733 xmpyu ${fni}L,${fm0}R,${fnm0} ; np[j]*m
735 xmpyu ${fai}R,${fbi},${fab1} ; ap[j]*bp[i]
736 fstds ${fab0},-16($xfer)
737 xmpyu ${fni}R,${fm0}R,${fnm1} ; np[j]*m
738 fstds ${fnm0},-8($xfer)
740 ldw 4($tp),$ti0 ; tp[j]
742 fstds ${fab1},0($xfer)
744 fstds ${fnm1},8($xfer)
747 add $ablo,$nmlo1,$nmlo1
749 addc %r0,$nmhi1,$nmhi1
751 add $hi1,$nmlo1,$nmlo1
756 stw $nmlo1,-4($tp) ; tp[j-1]
759 ldw 8($tp),$ti1 ; tp[j]
762 add $ablo,$nmlo0,$nmlo0
764 addc %r0,$nmhi0,$nmhi0
765 ldws,mb 8($xfer),$nmhi1
766 add $hi1,$nmlo0,$nmlo0
769 stws,ma $nmlo0,8($tp) ; tp[j-1]
771 addib,= -1,$num,L\$outerdone_pa11; i--
772 subi 0,$arrsz,$idx ; j=0
774 fldws,ma 4($bp),${fbi} ; bp[i]
775 flddx $idx($ap),${fai} ; ap[0]
778 flddx $idx($np),${fni} ; np[0]
779 fldws 8($xfer),${fti}R ; tp[0]
783 ldo 8($idx),$idx ; j++++
784 xmpyu ${fai}L,${fbi},${fab0} ; ap[0]*bp[i]
785 xmpyu ${fai}R,${fbi},${fab1} ; ap[1]*bp[i]
786 ldw 4($tp),$ti0 ; tp[j]
788 add $hi1,$nmlo1,$nmlo1
789 addc %r0,$nmhi1,$nmhi1
790 fstws,mb ${fab0}L,-8($xfer) ; save high part
791 add $ablo,$nmlo1,$nmlo1
793 fcpy,sgl %fr0,${fti}L ; zero high part
794 fcpy,sgl %fr0,${fab0}L
795 stw $nmlo1,-4($tp) ; tp[j-1]
797 fcnvxf,dbl,dbl ${fti},${fti} ; 32-bit unsigned int -> double
798 fcnvxf,dbl,dbl ${fab0},${fab0}
801 fadd,dbl ${fti},${fab0},${fab0} ; add tp[0]
804 fcnvfx,dbl,dbl ${fab0},${fab0} ; double -> 33-bit unsigned int
807 xmpyu ${fn0},${fab0}R,${fm0}
810 ldo `$LOCALS+32+4`($fp),$tp
818 ldw 4($tp),$ti0 ; tp[j]
820 add $hi1,$nmlo1,$nmlo1
821 addc %r0,$nmhi1,$nmhi1
822 add $ablo,$nmlo1,$nmlo1
824 stw $nmlo1,-4($tp) ; tp[j-1]
833 ldo `$LOCALS+32+4`($fp),$tp
834 sub %r0,%r0,%r0 ; clear borrow
841 addib,<> 4,$idx,L\$sub_pa11
850 sub $rp,$arrsz,$rp ; rewind rp
852 ldo `$LOCALS+32`($fp),$tp
856 addib,<> 4,$idx,L\$copy_pa11
865 ldi 1,%r28 ; signal "handled"
866 ldo $FRAME($fp),%sp ; destroy tp[num+1]
868 $POP `-$FRAME-$SAVED_RP`(%sp),%r2 ; standard epilogue
869 $POP `-$FRAME+1*$SIZE_T`(%sp),%r4
870 $POP `-$FRAME+2*$SIZE_T`(%sp),%r5
871 $POP `-$FRAME+3*$SIZE_T`(%sp),%r6
872 $POP `-$FRAME+4*$SIZE_T`(%sp),%r7
873 $POP `-$FRAME+5*$SIZE_T`(%sp),%r8
874 $POP `-$FRAME+6*$SIZE_T`(%sp),%r9
875 $POP `-$FRAME+7*$SIZE_T`(%sp),%r10
879 $POPMB -$FRAME(%sp),%r3
881 .STRINGZ "Montgomery Multiplication for PA-RISC, CRYPTOGAMS by <appro\@openssl.org>"
884 # Explicitly encode PA-RISC 2.0 instructions used in this module, so
885 # that it can be compiled with .LEVEL 1.0. It should be noted that I
886 # wouldn't have to do this, if GNU assembler understood .ALLOW 2.0
890 my ($mod,$args) = @_;
891 my $orig = "ldd$mod\t$args";
893 if ($args =~ /%r([0-9]+)\(%r([0-9]+)\),%r([0-9]+)/) # format 4
894 { my $opcode=(0x03<<26)|($2<<21)|($1<<16)|(3<<6)|$3;
895 sprintf "\t.WORD\t0x%08x\t; %s",$opcode,$orig;
897 elsif ($args =~ /(\-?[0-9]+)\(%r([0-9]+)\),%r([0-9]+)/) # format 5
898 { my $opcode=(0x03<<26)|($2<<21)|(1<<12)|(3<<6)|$3;
899 $opcode|=(($1&0xF)<<17)|(($1&0x10)<<12); # encode offset
900 $opcode|=(1<<5) if ($mod =~ /^,m/);
901 $opcode|=(1<<13) if ($mod =~ /^,mb/);
902 sprintf "\t.WORD\t0x%08x\t; %s",$opcode,$orig;
908 my ($mod,$args) = @_;
909 my $orig = "std$mod\t$args";
911 if ($args =~ /%r([0-9]+),(\-?[0-9]+)\(%r([0-9]+)\)/) # format 6
912 { my $opcode=(0x03<<26)|($3<<21)|($1<<16)|(1<<12)|(0xB<<6);
913 $opcode|=(($2&0xF)<<1)|(($2&0x10)>>4); # encode offset
914 $opcode|=(1<<5) if ($mod =~ /^,m/);
915 $opcode|=(1<<13) if ($mod =~ /^,mb/);
916 sprintf "\t.WORD\t0x%08x\t; %s",$opcode,$orig;
922 my ($mod,$args) = @_;
923 my $orig = "extrd$mod\t$args";
925 # I only have ",u" completer, it's implicitly encoded...
926 if ($args =~ /%r([0-9]+),([0-9]+),([0-9]+),%r([0-9]+)/) # format 15
927 { my $opcode=(0x36<<26)|($1<<21)|($4<<16);
929 $opcode |= (($2&0x20)<<6)|(($2&0x1f)<<5); # encode pos
930 $opcode |= (($len&0x20)<<7)|($len&0x1f); # encode len
931 sprintf "\t.WORD\t0x%08x\t; %s",$opcode,$orig;
933 elsif ($args =~ /%r([0-9]+),%sar,([0-9]+),%r([0-9]+)/) # format 12
934 { my $opcode=(0x34<<26)|($1<<21)|($3<<16)|(2<<11)|(1<<9);
936 $opcode |= (($len&0x20)<<3)|($len&0x1f); # encode len
937 $opcode |= (1<<13) if ($mod =~ /,\**=/);
938 sprintf "\t.WORD\t0x%08x\t; %s",$opcode,$orig;
944 my ($mod,$args) = @_;
945 my $orig = "shrpd$mod\t$args";
947 if ($args =~ /%r([0-9]+),%r([0-9]+),([0-9]+),%r([0-9]+)/) # format 14
948 { my $opcode=(0x34<<26)|($2<<21)|($1<<16)|(1<<10)|$4;
950 $opcode |= (($cpos&0x20)<<6)|(($cpos&0x1f)<<5); # encode sa
951 sprintf "\t.WORD\t0x%08x\t; %s",$opcode,$orig;
957 my ($mod,$args) = @_;
958 my $orig = "sub$mod\t$args";
960 if ($mod eq ",db" && $args =~ /%r([0-9]+),%r([0-9]+),%r([0-9]+)/) {
961 my $opcode=(0x02<<26)|($2<<21)|($1<<16)|$3;
962 $opcode|=(1<<10); # e1
963 $opcode|=(1<<8); # e2
965 sprintf "\t.WORD\t0x%08x\t; %s",$opcode,$orig
971 my ($mnemonic,$mod,$args)=@_;
972 my $opcode = eval("\$$mnemonic");
974 ref($opcode) eq 'CODE' ? &$opcode($mod,$args) : "\t$mnemonic$mod\t$args";
977 foreach (split("\n",$code)) {
978 s/\`([^\`]*)\`/eval $1/ge;
979 # flip word order in 64-bit mode...
980 s/(xmpyu\s+)($fai|$fni)([LR])/$1.$2.($3 eq "L"?"R":"L")/e if ($BN_SZ==8);
981 # assemble 2.0 instructions in 32-bit mode...
982 s/^\s+([a-z]+)([\S]*)\s+([\S]*)/&assemble($1,$2,$3)/e if ($BN_SZ==4);