]>
git.ipfire.org Git - thirdparty/openssl.git/blob - crypto/bn/asm/parisc-mont.pl
ed7df62815b2956585ea0cfdaccc8fc5b50387fc
2 # Copyright 2009-2018 The OpenSSL Project Authors. All Rights Reserved.
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
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 # ====================================================================
17 # On PA-7100LC this module performs ~90-50% better, less for longer
18 # keys, than code generated by gcc 3.2 for PA-RISC 1.1. Latter means
19 # that compiler utilized xmpyu instruction to perform 32x32=64-bit
20 # multiplication, which in turn means that "baseline" performance was
21 # optimal in respect to instruction set capabilities. Fair comparison
22 # with vendor compiler is problematic, because OpenSSL doesn't define
23 # BN_LLONG [presumably] for historical reasons, which drives compiler
24 # toward 4 times 16x16=32-bit multiplications [plus complementary
25 # shifts and additions] instead. This means that you should observe
26 # several times improvement over code generated by vendor compiler
27 # for PA-RISC 1.1, but the "baseline" is far from optimal. The actual
28 # improvement coefficient was never collected on PA-7100LC, or any
29 # other 1.1 CPU, because I don't have access to such machine with
30 # vendor compiler. But to give you a taste, PA-RISC 1.1 code path
31 # reportedly outperformed code generated by cc +DA1.1 +O3 by factor
34 # On PA-RISC 2.0 it has to compete with pa-risc2[W].s, which is
35 # reportedly ~2x faster than vendor compiler generated code [according
36 # to comment in pa-risc2[W].s]. Here comes a catch. Execution core of
37 # this implementation is actually 32-bit one, in the sense that it
38 # operates on 32-bit values. But pa-risc2[W].s operates on arrays of
39 # 64-bit BN_LONGs... How do they interoperate then? No problem. This
40 # module picks halves of 64-bit values in reverse order and pretends
41 # they were 32-bit BN_LONGs. But can 32-bit core compete with "pure"
42 # 64-bit code such as pa-risc2[W].s then? Well, the thing is that
43 # 32x32=64-bit multiplication is the best even PA-RISC 2.0 can do,
44 # i.e. there is no "wider" multiplication like on most other 64-bit
45 # platforms. This means that even being effectively 32-bit, this
46 # implementation performs "64-bit" computational task in same amount
47 # of arithmetic operations, most notably multiplications. It requires
48 # more memory references, most notably to tp[num], but this doesn't
49 # seem to exhaust memory port capacity. And indeed, dedicated PA-RISC
50 # 2.0 code path provides virtually same performance as pa-risc2[W].s:
51 # it's ~10% better for shortest key length and ~10% worse for longest
54 # In case it wasn't clear. The module has two distinct code paths:
55 # PA-RISC 1.1 and PA-RISC 2.0 ones. Latter features carry-free 64-bit
56 # additions and 64-bit integer loads, not to mention specific
57 # instruction scheduling. In 64-bit build naturally only 2.0 code path
58 # is assembled. In 32-bit application context both code paths are
59 # assembled, PA-RISC 2.0 CPU is detected at run-time and proper path
60 # is taken automatically. Also, in 32-bit build the module imposes
61 # couple of limitations: vector lengths has to be even and vector
62 # addresses has to be 64-bit aligned. Normally neither is a problem:
63 # most common key lengths are even and vectors are commonly malloc-ed,
64 # which ensures alignment.
66 # Special thanks to polarhome.com for providing HP-UX account on
67 # PA-RISC 1.1 machine, and to correspondent who chose to remain
68 # anonymous for testing the code on PA-RISC 2.0 machine.
70 $0 =~ m/(.*[\/\\])[^\
/\\]+$/; $dir=$1;
72 # $output is the last argument if it looks like a file (it has an extension)
73 # $flavour is the first argument if it doesn't look like a file
74 $output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m
|\
.\w
+$| ?
pop : undef;
75 $flavour = $#ARGV >= 0 && $ARGV[0] !~ m
|\
.| ?
shift : undef;
77 $output and open STDOUT
,">$output";
79 if ($flavour =~ /64/) {
90 $LEVEL ="1.1"; #$LEVEL.="\n\t.ALLOW\t2.0";
99 if (open CONF
,"<${dir}../../opensslconf.h") {
101 if (m/#\s*define\s+SIXTY_FOUR_BIT/) {
111 $FRAME=8*$SIZE_T+$FRAME_MARKER; # 8 saved regs + frame marker
112 # [+ argument transfer]
113 $LOCALS=$FRAME-$FRAME_MARKER;
114 $FRAME+=32; # local variables
124 $n0="%r22"; # passed through stack in 32-bit
125 $num="%r21"; # passed through stack in 32-bit
138 $xfer=$n0; # accommodates [-16..15] offset in fld[dw]s
140 $fm0="%fr4"; $fti=$fm0;
143 $fai="%fr6"; $fab0="%fr7"; $fab1="%fr8";
144 $fni="%fr9"; $fnm0="%fr10"; $fnm1="%fr11";
149 .SUBSPA \
$CODE\
$,QUAD
=0,ALIGN
=8,ACCESS
=0x2C,CODE_ONLY
151 .EXPORT bn_mul_mont
,ENTRY
,ARGW0
=GR
,ARGW1
=GR
,ARGW2
=GR
,ARGW3
=GR
155 .CALLINFO FRAME
=`$FRAME-8*$SIZE_T`,NO_CALLS
,SAVE_RP
,SAVE_SP
,ENTRY_GR
=6
157 $PUSH %r2,-$SAVED_RP(%sp) ; standard prologue
158 $PUSHMA %r3,$FRAME(%sp)
159 $PUSH %r4,`-$FRAME+1*$SIZE_T`(%sp)
160 $PUSH %r5,`-$FRAME+2*$SIZE_T`(%sp)
161 $PUSH %r6,`-$FRAME+3*$SIZE_T`(%sp)
162 $PUSH %r7,`-$FRAME+4*$SIZE_T`(%sp)
163 $PUSH %r8,`-$FRAME+5*$SIZE_T`(%sp)
164 $PUSH %r9,`-$FRAME+6*$SIZE_T`(%sp)
165 $PUSH %r10,`-$FRAME+7*$SIZE_T`(%sp)
168 $code.=<<___
if ($SIZE_T==4);
169 ldw
`-$FRAME_MARKER-4`($fp),$n0
170 ldw
`-$FRAME_MARKER-8`($fp),$num
174 $code.=<<___
if ($BN_SZ==4);
175 comiclr
,<= 6,$num,%r0 ; are vectors long enough?
177 ldi
0,%r28 ; signal
"unhandled"
178 add
,ev
%r0,$num,$num ; is
$num even?
182 extru
,= $ti1,31,3,%r0 ; are ap
and np
64-bit aligned?
189 fldws
,ma
4($bp),${fbi
} ; bp
[0]
191 $code.=<<___
if ($BN_SZ==8);
192 comib
,> 3,$num,L\
$abort ; are vectors long enough?
193 ldi
0,%r28 ; signal
"unhandled"
194 addl
$num,$num,$num ; I operate on
32-bit
values
196 fldws
4($n0),${fn0
} ; only low part of n0
197 fldws
4($bp),${fbi
} ; bp
[0] in flipped word order
200 fldds
0($ap),${fai
} ; ap
[0,1]
201 fldds
0($np),${fni
} ; np
[0,1]
203 sh2addl
$num,%r0,$arrsz
205 ldo
36($arrsz),$hi1 ; space
for tp
[num
+1]
206 andcm
$hi1,$hi0,$hi1 ; align
208 $PUSH $fp,-$SIZE_T(%sp)
210 ldo
`$LOCALS+16`($fp),$xfer
211 ldo
`$LOCALS+32+4`($fp),$tp
213 xmpyu
${fai
}L
,${fbi
},${fab0
} ; ap
[0]*bp
[0]
214 xmpyu
${fai
}R
,${fbi
},${fab1
} ; ap
[1]*bp
[0]
215 xmpyu
${fn0
},${fab0
}R
,${fm0
}
217 addl
$arrsz,$ap,$ap ; point at the end
219 subi
0,$arrsz,$idx ; j
=0
220 ldo
8($idx),$idx ; j
++++
222 xmpyu
${fni
}L
,${fm0
}R
,${fnm0
} ; np
[0]*m
223 xmpyu
${fni
}R
,${fm0
}R
,${fnm1
} ; np
[1]*m
224 fstds
${fab0
},-16($xfer)
225 fstds
${fnm0
},-8($xfer)
226 fstds
${fab1
},0($xfer)
227 fstds
${fnm1
},8($xfer)
228 flddx
$idx($ap),${fai
} ; ap
[2,3]
229 flddx
$idx($np),${fni
} ; np
[2,3]
231 $code.=<<___
if ($BN_SZ==4);
232 mtctl
$hi0,%cr11 ; $hi0 still holds
31
233 extrd
,u
,*= $hi0,%sar,1,$hi0 ; executes on PA
-RISC
1.0
237 $code.=<<___
; # PA-RISC 2.0 code-path
238 xmpyu
${fai
}L
,${fbi
},${fab0
} ; ap
[j
]*bp
[0]
239 xmpyu
${fni
}L
,${fm0
}R
,${fnm0
} ; np
[j
]*m
241 fstds
${fab0
},-16($xfer)
243 extrd
,u
$ab0,31,32,$hi0
244 extrd
,u
$ab0,63,32,$ab0
246 fstds
${fnm0
},-8($xfer)
247 ldo
8($idx),$idx ; j
++++
248 addl
$ab0,$nm0,$nm0 ; low part is discarded
249 extrd
,u
$nm0,31,32,$hi1
252 xmpyu
${fai
}R
,${fbi
},${fab1
} ; ap
[j
+1]*bp
[0]
253 xmpyu
${fni
}R
,${fm0
}R
,${fnm1
} ; np
[j
+1]*m
255 fstds
${fab1
},0($xfer)
257 extrd
,u
$ab1,31,32,$hi0
259 fstds
${fnm1
},8($xfer)
260 extrd
,u
$ab1,63,32,$ab1
262 flddx
$idx($ap),${fai
} ; ap
[j
,j
+1]
263 flddx
$idx($np),${fni
} ; np
[j
,j
+1]
265 extrd
,u
$nm1,31,32,$hi1
267 xmpyu
${fai
}L
,${fbi
},${fab0
} ; ap
[j
]*bp
[0]
268 xmpyu
${fni
}L
,${fm0
}R
,${fnm0
} ; np
[j
]*m
270 fstds
${fab0
},-16($xfer)
272 extrd
,u
$ab0,31,32,$hi0
274 fstds
${fnm0
},-8($xfer)
275 extrd
,u
$ab0,63,32,$ab0
277 stw
$nm1,-4($tp) ; tp
[j
-1]
279 stw
,ma
$nm0,8($tp) ; tp
[j
-1]
280 addib
,<> 8,$idx,L\
$1st ; j
++++
281 extrd
,u
$nm0,31,32,$hi1
283 xmpyu
${fai
}R
,${fbi
},${fab1
} ; ap
[j
]*bp
[0]
284 xmpyu
${fni
}R
,${fm0
}R
,${fnm1
} ; np
[j
]*m
286 fstds
${fab1
},0($xfer)
288 extrd
,u
$ab1,31,32,$hi0
290 fstds
${fnm1
},8($xfer)
291 extrd
,u
$ab1,63,32,$ab1
296 extrd
,u
$nm1,31,32,$hi1
299 extrd
,u
$ab0,31,32,$hi0
300 stw
$nm1,-4($tp) ; tp
[j
-1]
301 extrd
,u
$ab0,63,32,$ab0
306 extrd
,u
$nm0,31,32,$hi1
307 stw
,ma
$nm0,8($tp) ; tp
[j
-1]
309 ldo
-1($num),$num ; i
--
310 subi
0,$arrsz,$idx ; j
=0
312 $code.=<<___
if ($BN_SZ==4);
313 fldws
,ma
4($bp),${fbi
} ; bp
[1]
315 $code.=<<___
if ($BN_SZ==8);
316 fldws
0($bp),${fbi
} ; bp
[1] in flipped word order
319 flddx
$idx($ap),${fai
} ; ap
[0,1]
320 flddx
$idx($np),${fni
} ; np
[0,1]
321 fldws
8($xfer),${fti
}R
; tp
[0]
323 extrd
,u
$ab1,31,32,$hi0
324 extrd
,u
$ab1,63,32,$ab1
325 ldo
8($idx),$idx ; j
++++
326 xmpyu
${fai
}L
,${fbi
},${fab0
} ; ap
[0]*bp
[1]
327 xmpyu
${fai
}R
,${fbi
},${fab1
} ; ap
[1]*bp
[1]
330 extrd
,u
$nm1,31,32,$hi1
331 fstws
,mb
${fab0
}L
,-8($xfer) ; save high part
332 stw
$nm1,-4($tp) ; tp
[j
-1]
334 fcpy
,sgl
%fr0,${fti
}L
; zero high part
335 fcpy
,sgl
%fr0,${fab0
}L
337 extrd
,u
$hi0,31,32,$hi1
338 fcnvxf
,dbl
,dbl
${fti
},${fti
} ; 32-bit unsigned
int -> double
339 fcnvxf
,dbl
,dbl
${fab0
},${fab0
}
343 fadd
,dbl
${fti
},${fab0
},${fab0
} ; add tp
[0]
344 fcnvfx
,dbl
,dbl
${fab0
},${fab0
} ; double
-> 33-bit unsigned
int
345 xmpyu
${fn0
},${fab0
}R
,${fm0
}
346 ldo
`$LOCALS+32+4`($fp),$tp
348 xmpyu
${fni
}L
,${fm0
}R
,${fnm0
} ; np
[0]*m
349 xmpyu
${fni
}R
,${fm0
}R
,${fnm1
} ; np
[1]*m
350 fstds
${fab0
},-16($xfer) ; 33-bit value
351 fstds
${fnm0
},-8($xfer)
352 flddx
$idx($ap),${fai
} ; ap
[2]
353 flddx
$idx($np),${fni
} ; np
[2]
354 ldo
8($idx),$idx ; j
++++
355 ldd
-16($xfer),$ab0 ; 33-bit value
357 ldw
0($xfer),$hi0 ; high part
359 xmpyu
${fai
}L
,${fbi
},${fab0
} ; ap
[j
]*bp
[i
]
360 xmpyu
${fni
}L
,${fm0
}R
,${fnm0
} ; np
[j
]*m
361 extrd
,u
$ab0,31,32,$ti0 ; carry bit
362 extrd
,u
$ab0,63,32,$ab0
363 fstds
${fab1
},0($xfer)
364 addl
$ti0,$hi0,$hi0 ; account carry bit
365 fstds
${fnm1
},8($xfer)
366 addl
$ab0,$nm0,$nm0 ; low part is discarded
367 ldw
0($tp),$ti1 ; tp
[1]
368 extrd
,u
$nm0,31,32,$hi1
369 fstds
${fab0
},-16($xfer)
370 fstds
${fnm0
},-8($xfer)
373 xmpyu
${fai
}R
,${fbi
},${fab1
} ; ap
[j
+1]*bp
[i
]
374 xmpyu
${fni
}R
,${fm0
}R
,${fnm1
} ; np
[j
+1]*m
376 fstds
${fab1
},0($xfer)
380 fstds
${fnm1
},8($xfer)
381 extrd
,u
$ab1,31,32,$hi0
382 extrd
,u
$ab1,63,32,$ab1
383 flddx
$idx($ap),${fai
} ; ap
[j
,j
+1]
384 flddx
$idx($np),${fni
} ; np
[j
,j
+1]
387 ldw
4($tp),$ti0 ; tp
[j
]
388 stw
$nm1,-4($tp) ; tp
[j
-1]
390 xmpyu
${fai
}L
,${fbi
},${fab0
} ; ap
[j
]*bp
[i
]
391 xmpyu
${fni
}L
,${fm0
}R
,${fnm0
} ; np
[j
]*m
393 fstds
${fab0
},-16($xfer)
397 fstds
${fnm0
},-8($xfer)
398 extrd
,u
$ab0,31,32,$hi0
399 extrd
,u
$nm1,31,32,$hi1
400 ldw
8($tp),$ti1 ; tp
[j
]
401 extrd
,u
$ab0,63,32,$ab0
404 stw
,ma
$nm0,8($tp) ; tp
[j
-1]
405 addib
,<> 8,$idx,L\
$inner ; j
++++
406 extrd
,u
$nm0,31,32,$hi1
408 xmpyu
${fai
}R
,${fbi
},${fab1
} ; ap
[j
]*bp
[i
]
409 xmpyu
${fni
}R
,${fm0
}R
,${fnm1
} ; np
[j
]*m
411 fstds
${fab1
},0($xfer)
415 fstds
${fnm1
},8($xfer)
416 extrd
,u
$ab1,31,32,$hi0
417 extrd
,u
$ab1,63,32,$ab1
418 ldw
4($tp),$ti0 ; tp
[j
]
423 extrd
,u
$nm1,31,32,$hi1
427 stw
$nm1,-4($tp) ; tp
[j
-1]
428 extrd
,u
$ab0,31,32,$hi0
429 ldw
8($tp),$ti1 ; tp
[j
]
430 extrd
,u
$ab0,63,32,$ab0
435 extrd
,u
$nm0,31,32,$hi1
436 stw
,ma
$nm0,8($tp) ; tp
[j
-1]
438 addib
,= -1,$num,L\
$outerdone ; i
--
439 subi
0,$arrsz,$idx ; j
=0
441 $code.=<<___
if ($BN_SZ==4);
442 fldws
,ma
4($bp),${fbi
} ; bp
[i
]
444 $code.=<<___
if ($BN_SZ==8);
445 ldi
12,$ti0 ; bp
[i
] in flipped word order
446 addl
,ev
%r0,$num,$num
452 flddx
$idx($ap),${fai
} ; ap
[0]
454 flddx
$idx($np),${fni
} ; np
[0]
455 fldws
8($xfer),${fti
}R
; tp
[0]
457 extrd
,u
$ab1,31,32,$hi0
458 extrd
,u
$ab1,63,32,$ab1
460 ldo
8($idx),$idx ; j
++++
461 xmpyu
${fai
}L
,${fbi
},${fab0
} ; ap
[0]*bp
[i
]
462 xmpyu
${fai
}R
,${fbi
},${fab1
} ; ap
[1]*bp
[i
]
463 ldw
4($tp),$ti0 ; tp
[j
]
466 fstws
,mb
${fab0
}L
,-8($xfer) ; save high part
468 extrd
,u
$nm1,31,32,$hi1
469 fcpy
,sgl
%fr0,${fti
}L
; zero high part
470 fcpy
,sgl
%fr0,${fab0
}L
471 stw
$nm1,-4($tp) ; tp
[j
-1]
473 fcnvxf
,dbl
,dbl
${fti
},${fti
} ; 32-bit unsigned
int -> double
474 fcnvxf
,dbl
,dbl
${fab0
},${fab0
}
476 fadd
,dbl
${fti
},${fab0
},${fab0
} ; add tp
[0]
478 extrd
,u
$hi0,31,32,$hi1
479 fcnvfx
,dbl
,dbl
${fab0
},${fab0
} ; double
-> 33-bit unsigned
int
482 xmpyu
${fn0
},${fab0
}R
,${fm0
}
485 ldo
`$LOCALS+32+4`($fp),$tp
490 extrd
,u
$ab1,31,32,$hi0
491 extrd
,u
$ab1,63,32,$ab1
493 ldw
4($tp),$ti0 ; tp
[j
]
497 extrd
,u
$nm1,31,32,$hi1
498 stw
$nm1,-4($tp) ; tp
[j
-1]
502 extrd
,u
$hi0,31,32,$hi1
506 ldo
`$LOCALS+32`($fp),$tp
507 sub %r0,%r0,%r0 ; clear borrow
509 $code.=<<___
if ($BN_SZ==4);
511 extru
,= $rp,31,3,%r0 ; is rp
64-bit aligned?
518 addib
,<> 4,$idx,L\
$sub
523 $code.=<<___
if ($BN_SZ==8);
527 shrpd
$ti0,$ti0,32,$ti0 ; flip word order
528 std
$ti0,-8($tp) ; save flipped value
529 sub,db
$ti0,$hi0,$hi1
531 addib
,<> 8,$idx,L\
$sub
534 extrd
,u
$ti0,31,32,$ti0 ; carry
in flipped word order
538 ldo
`$LOCALS+32`($fp),$tp
539 sub $rp,$arrsz,$rp ; rewind rp
547 addib
,<> 8,$idx,L\
$copy
551 if ($BN_SZ==4) { # PA-RISC 1.1 code-path
565 xmpyu
${fai
}L
,${fbi
},${fab0
} ; ap
[j
]*bp
[0]
566 xmpyu
${fni
}L
,${fm0
}R
,${fnm0
} ; np
[j
]*m
571 fstds
${fab0
},-16($xfer)
572 fstds
${fnm0
},-8($xfer)
574 ldo
8($idx),$idx ; j
++++
575 add
$ablo,$nmlo0,$nmlo0 ; discarded
582 xmpyu
${fai
}R
,${fbi
},${fab1
} ; ap
[j
+1]*bp
[0]
583 flddx
$idx($ap),${fai
} ; ap
[j
,j
+1]
584 xmpyu
${fni
}R
,${fm0
}R
,${fnm1
} ; np
[j
+1]*m
585 flddx
$idx($np),${fni
} ; np
[j
,j
+1]
590 add
$ablo,$nmlo1,$nmlo1
591 fstds
${fab1
},0($xfer)
592 addc
%r0,$nmhi1,$nmhi1
593 fstds
${fnm1
},8($xfer)
594 add
$hi1,$nmlo1,$nmlo1
599 xmpyu
${fai
}L
,${fbi
},${fab0
} ; ap
[j
]*bp
[0]
601 xmpyu
${fni
}L
,${fm0
}R
,${fnm0
} ; np
[j
]*m
604 stw
$nmlo1,-4($tp) ; tp
[j
-1]
606 fstds
${fab0
},-16($xfer)
607 add
$ablo,$nmlo0,$nmlo0
608 fstds
${fnm0
},-8($xfer)
609 addc
%r0,$nmhi0,$nmhi0
611 add
$hi1,$nmlo0,$nmlo0
613 stws
,ma
$nmlo0,8($tp) ; tp
[j
-1]
614 addib
,<> 8,$idx,L\
$1st_pa11 ; j
++++
619 xmpyu
${fai
}R
,${fbi
},${fab1
} ; ap
[j
]*bp
[0]
620 xmpyu
${fni
}R
,${fm0
}R
,${fnm1
} ; np
[j
]*m
622 fstds
${fab1
},0($xfer)
624 fstds
${fnm1
},8($xfer)
625 add
$ablo,$nmlo1,$nmlo1
627 addc
%r0,$nmhi1,$nmhi1
629 add
$hi1,$nmlo1,$nmlo1
635 stw
$nmlo1,-4($tp) ; tp
[j
-1]
638 add
$ablo,$nmlo0,$nmlo0
640 addc
%r0,$nmhi0,$nmhi0
641 ldws
,mb
8($xfer),$nmhi1
642 add
$hi1,$nmlo0,$nmlo0
645 stws
,ma
$nmlo0,8($tp) ; tp
[j
-1]
647 ldo
-1($num),$num ; i
--
648 subi
0,$arrsz,$idx ; j
=0
650 fldws
,ma
4($bp),${fbi
} ; bp
[1]
651 flddx
$idx($ap),${fai
} ; ap
[0,1]
652 flddx
$idx($np),${fni
} ; np
[0,1]
653 fldws
8($xfer),${fti
}R
; tp
[0]
656 ldo
8($idx),$idx ; j
++++
657 xmpyu
${fai
}L
,${fbi
},${fab0
} ; ap
[0]*bp
[1]
658 xmpyu
${fai
}R
,${fbi
},${fab1
} ; ap
[1]*bp
[1]
659 add
$hi1,$nmlo1,$nmlo1
660 addc
%r0,$nmhi1,$nmhi1
661 add
$ablo,$nmlo1,$nmlo1
663 fstws
,mb
${fab0
}L
,-8($xfer) ; save high part
664 stw
$nmlo1,-4($tp) ; tp
[j
-1]
666 fcpy
,sgl
%fr0,${fti
}L
; zero high part
667 fcpy
,sgl
%fr0,${fab0
}L
670 fcnvxf
,dbl
,dbl
${fti
},${fti
} ; 32-bit unsigned
int -> double
671 fcnvxf
,dbl
,dbl
${fab0
},${fab0
}
675 fadd
,dbl
${fti
},${fab0
},${fab0
} ; add tp
[0]
676 fcnvfx
,dbl
,dbl
${fab0
},${fab0
} ; double
-> 33-bit unsigned
int
677 xmpyu
${fn0
},${fab0
}R
,${fm0
}
678 ldo
`$LOCALS+32+4`($fp),$tp
680 xmpyu
${fni
}L
,${fm0
}R
,${fnm0
} ; np
[0]*m
681 xmpyu
${fni
}R
,${fm0
}R
,${fnm1
} ; np
[1]*m
682 fstds
${fab0
},-16($xfer) ; 33-bit value
683 fstds
${fnm0
},-8($xfer)
684 flddx
$idx($ap),${fai
} ; ap
[2,3]
685 flddx
$idx($np),${fni
} ; np
[2,3]
686 ldw
-16($xfer),$abhi ; carry bit actually
687 ldo
8($idx),$idx ; j
++++
691 ldw
0($xfer),$hi0 ; high part
693 xmpyu
${fai
}L
,${fbi
},${fab0
} ; ap
[j
]*bp
[i
]
694 xmpyu
${fni
}L
,${fm0
}R
,${fnm0
} ; np
[j
]*m
695 fstds
${fab1
},0($xfer)
696 addl
$abhi,$hi0,$hi0 ; account carry bit
697 fstds
${fnm1
},8($xfer)
698 add
$ablo,$nmlo0,$nmlo0 ; discarded
699 ldw
0($tp),$ti1 ; tp
[1]
701 fstds
${fab0
},-16($xfer)
702 fstds
${fnm0
},-8($xfer)
707 xmpyu
${fai
}R
,${fbi
},${fab1
} ; ap
[j
+1]*bp
[i
]
708 flddx
$idx($ap),${fai
} ; ap
[j
,j
+1]
709 xmpyu
${fni
}R
,${fm0
}R
,${fnm1
} ; np
[j
+1]*m
710 flddx
$idx($np),${fni
} ; np
[j
,j
+1]
712 ldw
4($tp),$ti0 ; tp
[j
]
718 fstds
${fab1
},0($xfer)
719 add
$ablo,$nmlo1,$nmlo1
720 fstds
${fnm1
},8($xfer)
721 addc
%r0,$nmhi1,$nmhi1
723 add
$hi1,$nmlo1,$nmlo1
727 xmpyu
${fai
}L
,${fbi
},${fab0
} ; ap
[j
]*bp
[i
]
728 ldw
8($tp),$ti1 ; tp
[j
]
729 xmpyu
${fni
}L
,${fm0
}R
,${fnm0
} ; np
[j
]*m
734 stw
$nmlo1,-4($tp) ; tp
[j
-1]
736 fstds
${fab0
},-16($xfer)
738 fstds
${fnm0
},-8($xfer)
739 add
$ablo,$nmlo0,$nmlo0
741 addc
%r0,$nmhi0,$nmhi0
743 add
$hi1,$nmlo0,$nmlo0
744 stws
,ma
$nmlo0,8($tp) ; tp
[j
-1]
745 addib
,<> 8,$idx,L\
$inner_pa11 ; j
++++
748 xmpyu
${fai
}R
,${fbi
},${fab1
} ; ap
[j
]*bp
[i
]
750 xmpyu
${fni
}R
,${fm0
}R
,${fnm1
} ; np
[j
]*m
753 ldw
4($tp),$ti0 ; tp
[j
]
755 fstds
${fab1
},0($xfer)
757 fstds
${fnm1
},8($xfer)
760 add
$ablo,$nmlo1,$nmlo1
762 addc
%r0,$nmhi1,$nmhi1
764 add
$hi1,$nmlo1,$nmlo1
769 stw
$nmlo1,-4($tp) ; tp
[j
-1]
772 ldw
8($tp),$ti1 ; tp
[j
]
775 add
$ablo,$nmlo0,$nmlo0
777 addc
%r0,$nmhi0,$nmhi0
778 ldws
,mb
8($xfer),$nmhi1
779 add
$hi1,$nmlo0,$nmlo0
782 stws
,ma
$nmlo0,8($tp) ; tp
[j
-1]
784 addib
,= -1,$num,L\
$outerdone_pa11; i
--
785 subi
0,$arrsz,$idx ; j
=0
787 fldws
,ma
4($bp),${fbi
} ; bp
[i
]
788 flddx
$idx($ap),${fai
} ; ap
[0]
791 flddx
$idx($np),${fni
} ; np
[0]
792 fldws
8($xfer),${fti
}R
; tp
[0]
796 ldo
8($idx),$idx ; j
++++
797 xmpyu
${fai
}L
,${fbi
},${fab0
} ; ap
[0]*bp
[i
]
798 xmpyu
${fai
}R
,${fbi
},${fab1
} ; ap
[1]*bp
[i
]
799 ldw
4($tp),$ti0 ; tp
[j
]
801 add
$hi1,$nmlo1,$nmlo1
802 addc
%r0,$nmhi1,$nmhi1
803 fstws
,mb
${fab0
}L
,-8($xfer) ; save high part
804 add
$ablo,$nmlo1,$nmlo1
806 fcpy
,sgl
%fr0,${fti
}L
; zero high part
807 fcpy
,sgl
%fr0,${fab0
}L
808 stw
$nmlo1,-4($tp) ; tp
[j
-1]
810 fcnvxf
,dbl
,dbl
${fti
},${fti
} ; 32-bit unsigned
int -> double
811 fcnvxf
,dbl
,dbl
${fab0
},${fab0
}
814 fadd
,dbl
${fti
},${fab0
},${fab0
} ; add tp
[0]
817 fcnvfx
,dbl
,dbl
${fab0
},${fab0
} ; double
-> 33-bit unsigned
int
820 xmpyu
${fn0
},${fab0
}R
,${fm0
}
823 ldo
`$LOCALS+32+4`($fp),$tp
831 ldw
4($tp),$ti0 ; tp
[j
]
833 add
$hi1,$nmlo1,$nmlo1
834 addc
%r0,$nmhi1,$nmhi1
835 add
$ablo,$nmlo1,$nmlo1
837 stw
$nmlo1,-4($tp) ; tp
[j
-1]
846 ldo
`$LOCALS+32+4`($fp),$tp
847 sub %r0,%r0,%r0 ; clear borrow
854 addib
,<> 4,$idx,L\
$sub_pa11
859 ldo
`$LOCALS+32`($fp),$tp
860 sub $rp,$arrsz,$rp ; rewind rp
868 addib
,<> 4,$idx,L\
$copy_pa11
877 ldi
1,%r28 ; signal
"handled"
878 ldo
$FRAME($fp),%sp ; destroy tp
[num
+1]
880 $POP `-$FRAME-$SAVED_RP`(%sp),%r2 ; standard epilogue
881 $POP `-$FRAME+1*$SIZE_T`(%sp),%r4
882 $POP `-$FRAME+2*$SIZE_T`(%sp),%r5
883 $POP `-$FRAME+3*$SIZE_T`(%sp),%r6
884 $POP `-$FRAME+4*$SIZE_T`(%sp),%r7
885 $POP `-$FRAME+5*$SIZE_T`(%sp),%r8
886 $POP `-$FRAME+6*$SIZE_T`(%sp),%r9
887 $POP `-$FRAME+7*$SIZE_T`(%sp),%r10
891 $POPMB -$FRAME(%sp),%r3
893 .STRINGZ
"Montgomery Multiplication for PA-RISC, CRYPTOGAMS by <appro\@openssl.org>"
896 # Explicitly encode PA-RISC 2.0 instructions used in this module, so
897 # that it can be compiled with .LEVEL 1.0. It should be noted that I
898 # wouldn't have to do this, if GNU assembler understood .ALLOW 2.0
902 my ($mod,$args) = @_;
903 my $orig = "ldd$mod\t$args";
905 if ($args =~ /%r([0-9]+)\(%r([0-9]+)\),%r([0-9]+)/) # format 4
906 { my $opcode=(0x03<<26)|($2<<21)|($1<<16)|(3<<6)|$3;
907 sprintf "\t.WORD\t0x%08x\t; %s",$opcode,$orig;
909 elsif ($args =~ /(\-?[0-9]+)\(%r([0-9]+)\),%r([0-9]+)/) # format 5
910 { my $opcode=(0x03<<26)|($2<<21)|(1<<12)|(3<<6)|$3;
911 $opcode|=(($1&0xF)<<17)|(($1&0x10)<<12); # encode offset
912 $opcode|=(1<<5) if ($mod =~ /^,m/);
913 $opcode|=(1<<13) if ($mod =~ /^,mb/);
914 sprintf "\t.WORD\t0x%08x\t; %s",$opcode,$orig;
920 my ($mod,$args) = @_;
921 my $orig = "std$mod\t$args";
923 if ($args =~ /%r([0-9]+),(\-?[0-9]+)\(%r([0-9]+)\)/) # format 6
924 { my $opcode=(0x03<<26)|($3<<21)|($1<<16)|(1<<12)|(0xB<<6);
925 $opcode|=(($2&0xF)<<1)|(($2&0x10)>>4); # encode offset
926 $opcode|=(1<<5) if ($mod =~ /^,m/);
927 $opcode|=(1<<13) if ($mod =~ /^,mb/);
928 sprintf "\t.WORD\t0x%08x\t; %s",$opcode,$orig;
934 my ($mod,$args) = @_;
935 my $orig = "extrd$mod\t$args";
937 # I only have ",u" completer, it's implicitly encoded...
938 if ($args =~ /%r([0-9]+),([0-9]+),([0-9]+),%r([0-9]+)/) # format 15
939 { my $opcode=(0x36<<26)|($1<<21)|($4<<16);
941 $opcode |= (($2&0x20)<<6)|(($2&0x1f)<<5); # encode pos
942 $opcode |= (($len&0x20)<<7)|($len&0x1f); # encode len
943 sprintf "\t.WORD\t0x%08x\t; %s",$opcode,$orig;
945 elsif ($args =~ /%r([0-9]+),%sar,([0-9]+),%r([0-9]+)/) # format 12
946 { my $opcode=(0x34<<26)|($1<<21)|($3<<16)|(2<<11)|(1<<9);
948 $opcode |= (($len&0x20)<<3)|($len&0x1f); # encode len
949 $opcode |= (1<<13) if ($mod =~ /,\**=/);
950 sprintf "\t.WORD\t0x%08x\t; %s",$opcode,$orig;
956 my ($mod,$args) = @_;
957 my $orig = "shrpd$mod\t$args";
959 if ($args =~ /%r([0-9]+),%r([0-9]+),([0-9]+),%r([0-9]+)/) # format 14
960 { my $opcode=(0x34<<26)|($2<<21)|($1<<16)|(1<<10)|$4;
962 $opcode |= (($cpos&0x20)<<6)|(($cpos&0x1f)<<5); # encode sa
963 sprintf "\t.WORD\t0x%08x\t; %s",$opcode,$orig;
969 my ($mod,$args) = @_;
970 my $orig = "sub$mod\t$args";
972 if ($mod eq ",db" && $args =~ /%r([0-9]+),%r([0-9]+),%r([0-9]+)/) {
973 my $opcode=(0x02<<26)|($2<<21)|($1<<16)|$3;
974 $opcode|=(1<<10); # e1
975 $opcode|=(1<<8); # e2
977 sprintf "\t.WORD\t0x%08x\t; %s",$opcode,$orig
983 my ($mnemonic,$mod,$args)=@_;
984 my $opcode = eval("\$$mnemonic");
986 ref($opcode) eq 'CODE' ?
&$opcode($mod,$args) : "\t$mnemonic$mod\t$args";
989 if (`$ENV{CC} -Wa,-v -c -o /dev/null -x assembler /dev/null 2>&1`
990 =~ /GNU assembler/) {
994 foreach (split("\n",$code)) {
995 s/\`([^\`]*)\`/eval $1/ge;
996 # flip word order in 64-bit mode...
997 s/(xmpyu\s+)($fai|$fni)([LR])/$1.$2.($3 eq "L"?"R":"L")/e if ($BN_SZ==8);
998 # assemble 2.0 instructions in 32-bit mode...
999 s/^\s+([a-z]+)([\S]*)\s+([\S]*)/&assemble($1,$2,$3)/e if ($BN_SZ==4);
1001 s/(\.LEVEL\s+2\.0)W/$1w/ if ($gnuas && $SIZE_T==8);
1002 s/\.SPACE\s+\$TEXT\$/.text/ if ($gnuas && $SIZE_T==8);
1003 s/\.SUBSPA.*// if ($gnuas && $SIZE_T==8);
1004 s/\bbv\b/bve/ if ($SIZE_T==8);
1008 close STDOUT
or die "error closing STDOUT: $!";