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
# ====================================================================
12
# The reason for undertaken effort is basically following. Even though
13
# Power 6 CPU operates at incredible 4.7GHz clock frequency, its PKI
14
# performance was observed to be less than impressive, essentially as
15
# fast as 1.8GHz PPC970, or 2.6 times(!) slower than one would hope.
16
# Well, it's not surprising that IBM had to make some sacrifices to
17
# boost the clock frequency that much, but no overall improvement?
18
# Having observed how much difference did switching to FPU make on
19
# UltraSPARC, playing same stunt on Power 6 appeared appropriate...
20
# Unfortunately the resulting performance improvement is not as
21
# impressive, ~30%, and in absolute terms is still very far from what
22
# one would expect from 4.7GHz CPU. There is a chance that I'm doing
23
# something wrong, but in the lack of assembler level micro-profiling
24
# data or at least decent platform guide I can't tell... Or better
25
# results might be achieved with VMX... Anyway, this module provides
26
# *worse* performance on other PowerPC implementations, ~40-15% slower
27
# on PPC970 depending on key length and ~40% slower on Power 5 for all
28
# key lengths. As it's obviously inappropriate as "best all-round"
29
# alternative, it has to be complemented with run-time CPU family
30
# detection. Oh! It should also be noted that unlike other PowerPC
31
# implementation IALU ppc-mont.pl module performs *suboptimaly* on
32
# >=1024-bit key lengths on Power 6. It should also be noted that
33
# *everything* said so far applies to 64-bit builds! As far as 32-bit
34
# application executed on 64-bit CPU goes, this module is likely to
35
# become preferred choice, because it's easy to adapt it for such
36
# case and *is* faster than 32-bit ppc-mont.pl on *all* processors.
40
# Micro-profiling assisted optimization results in ~15% improvement
41
# over original ppc64-mont.pl version, or overall ~50% improvement
42
# over ppc.pl module on Power 6. If compared to ppc-mont.pl on same
43
# Power 6 CPU, this module is 5-150% faster depending on key length,
44
# [hereafter] more for longer keys. But if compared to ppc-mont.pl
45
# on 1.8GHz PPC970, it's only 5-55% faster. Still far from impressive
46
# in absolute terms, but it's apparently the way Power 6 is...
50
# Adapted for 32-bit build this module delivers 25-120%, yes, more
51
# than *twice* for longer keys, performance improvement over 32-bit
52
# ppc-mont.pl on 1.8GHz PPC970. However! This implementation utilizes
53
# even 64-bit integer operations and the trouble is that most PPC
54
# operating systems don't preserve upper halves of general purpose
55
# registers upon 32-bit signal delivery. They do preserve them upon
56
# context switch, but not signalling:-( This means that asynchronous
57
# signals have to be blocked upon entry to this subroutine. Signal
58
# masking (and of course complementary unmasking) has quite an impact
59
# on performance, naturally larger for shorter keys. It's so severe
60
# that 512-bit key performance can be as low as 1/3 of expected one.
61
# This is why this routine can be engaged for longer key operations
62
# only on these OSes, see crypto/ppccap.c for further details. MacOS X
63
# is an exception from this and doesn't require signal masking, and
64
# that's where above improvement coefficients were collected. For
65
# others alternative would be to break dependence on upper halves of
66
# GPRs by sticking to 32-bit integer operations...
70
if ($flavour =~ /32/) {
73
$fname= "bn_mul_mont_fpu64";
75
$STUX= "stwux"; # store indexed and update
78
} elsif ($flavour =~ /64/) {
81
$fname= "bn_mul_mont_fpu64";
83
# same as above, but 64-bit mnemonics...
84
$STUX= "stdux"; # store indexed and update
87
} else { die "nonsense $flavour"; }
89
$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
90
( $xlate="${dir}ppc-xlate.pl" and -f $xlate ) or
91
( $xlate="${dir}../../perlasm/ppc-xlate.pl" and -f $xlate) or
92
die "can't locate ppc-xlate.pl";
94
open STDOUT,"| $^X $xlate $flavour ".shift || die "can't call $xlate: $!";
96
$FRAME=64; # padded frame header
108
$rp="r9"; # $rp is reassigned
112
# non-volatile registers
113
$nap_d="r22"; # interleaved ap and np in double format
115
$t0="r24"; # temporary registers
124
# PPC offers enough register bank capacity to unroll inner loops twice
148
$ba="f0"; $bb="f1"; $bc="f2"; $bd="f3";
149
$na="f4"; $nb="f5"; $nc="f6"; $nd="f7";
150
$dota="f8"; $dotb="f9";
151
$A0="f10"; $A1="f11"; $A2="f12"; $A3="f13";
152
$N0="f20"; $N1="f21"; $N2="f22"; $N3="f23";
153
$T0a="f24"; $T0b="f25";
154
$T1a="f26"; $T1b="f27";
155
$T2a="f28"; $T2b="f29";
156
$T3a="f30"; $T3b="f31";
158
# sp----------->+-------------------------------+
160
# +-------------------------------+
162
# +64 +-------------------------------+
163
# | 16 gpr<->fpr transfer zone |
166
# +16*8 +-------------------------------+
167
# | __int64 tmp[-1] |
168
# +-------------------------------+
169
# | __int64 tmp[num] |
173
# +(num+1)*8 +-------------------------------+
174
# | padding to 64 byte boundary |
176
# +X +-------------------------------+
177
# | double nap_d[4*num] |
181
# +-------------------------------+
183
# -12*size_t +-------------------------------+
184
# | 10 saved gpr, r22-r31 |
187
# -12*8 +-------------------------------+
188
# | 12 saved fpr, f20-f31 |
191
# +-------------------------------+
200
cmpwi $num,`3*8/$SIZE_T`
201
mr $rp,r3 ; $rp is reassigned
202
li r3,0 ; possible "not handled" return code
204
andi. r0,$num,`16/$SIZE_T-1` ; $num has to be "even"
207
slwi $num,$num,`log($SIZE_T)/log(2)` ; num*=sizeof(BN_LONG)
209
slwi $tp,$num,2 ; place for {an}p_{lh}[num], i.e. 4*num
210
add $tp,$tp,$num ; place for tp[num+1]
211
addi $tp,$tp,`$FRAME+$TRANSFER+8+64+$RZONE`
212
subf $tp,$tp,$sp ; $sp-$tp
213
and $tp,$tp,$i ; minimize TLB usage
214
subf $tp,$sp,$tp ; $tp-$sp
216
$STUX $sp,$sp,$tp ; alloca
218
$PUSH r22,`-12*8-10*$SIZE_T`($i)
219
$PUSH r23,`-12*8-9*$SIZE_T`($i)
220
$PUSH r24,`-12*8-8*$SIZE_T`($i)
221
$PUSH r25,`-12*8-7*$SIZE_T`($i)
222
$PUSH r26,`-12*8-6*$SIZE_T`($i)
223
$PUSH r27,`-12*8-5*$SIZE_T`($i)
224
$PUSH r28,`-12*8-4*$SIZE_T`($i)
225
$PUSH r29,`-12*8-3*$SIZE_T`($i)
226
$PUSH r30,`-12*8-2*$SIZE_T`($i)
227
$PUSH r31,`-12*8-1*$SIZE_T`($i)
241
$code.=<<___ if ($SIZE_T==8);
242
ld $a0,0($ap) ; pull ap[0] value
243
ld $n0,0($n0) ; pull n0[0] value
244
ld $t3,0($bp) ; bp[0]
246
$code.=<<___ if ($SIZE_T==4);
248
lwz $a0,0($ap) ; pull ap[0,1] value
250
lwz $n0,0($t1) ; pull n0[0,1] value
252
lwz $t3,0($bp) ; bp[0,1]
259
addi $tp,$sp,`$FRAME+$TRANSFER+8+64`
262
and $nap_d,$nap_d,$i ; align to 64 bytes
264
mulld $t7,$a0,$t3 ; ap[0]*bp[0]
265
; nap_d is off by 1, because it's used with stfdu/lfdu
266
addi $nap_d,$nap_d,-8
267
srwi $j,$num,`3+1` ; counter register, num/2
268
mulld $t7,$t7,$n0 ; tp[0]*n0
270
addi $tp,$sp,`$FRAME+$TRANSFER-8`
274
; transfer bp[0] to FPU as 4x16-bit values
279
std $t0,`$FRAME+0`($sp)
280
std $t1,`$FRAME+8`($sp)
281
std $t2,`$FRAME+16`($sp)
282
std $t3,`$FRAME+24`($sp)
283
; transfer (ap[0]*bp[0])*n0 to FPU as 4x16-bit values
288
std $t4,`$FRAME+32`($sp)
289
std $t5,`$FRAME+40`($sp)
290
std $t6,`$FRAME+48`($sp)
291
std $t7,`$FRAME+56`($sp)
293
$code.=<<___ if ($SIZE_T==8);
294
lwz $t0,4($ap) ; load a[j] as 32-bit word pair
296
lwz $t2,12($ap) ; load a[j+1] as 32-bit word pair
298
lwz $t4,4($np) ; load n[j] as 32-bit word pair
300
lwz $t6,12($np) ; load n[j+1] as 32-bit word pair
303
$code.=<<___ if ($SIZE_T==4);
304
lwz $t0,0($ap) ; load a[j..j+3] as 32-bit word pairs
308
lwz $t4,0($np) ; load n[j..j+3] as 32-bit word pairs
314
lfd $ba,`$FRAME+0`($sp)
315
lfd $bb,`$FRAME+8`($sp)
316
lfd $bc,`$FRAME+16`($sp)
317
lfd $bd,`$FRAME+24`($sp)
318
lfd $na,`$FRAME+32`($sp)
319
lfd $nb,`$FRAME+40`($sp)
320
lfd $nc,`$FRAME+48`($sp)
321
lfd $nd,`$FRAME+56`($sp)
322
std $t0,`$FRAME+64`($sp)
323
std $t1,`$FRAME+72`($sp)
324
std $t2,`$FRAME+80`($sp)
325
std $t3,`$FRAME+88`($sp)
326
std $t4,`$FRAME+96`($sp)
327
std $t5,`$FRAME+104`($sp)
328
std $t6,`$FRAME+112`($sp)
329
std $t7,`$FRAME+120`($sp)
339
lfd $A0,`$FRAME+64`($sp)
340
lfd $A1,`$FRAME+72`($sp)
341
lfd $A2,`$FRAME+80`($sp)
342
lfd $A3,`$FRAME+88`($sp)
343
lfd $N0,`$FRAME+96`($sp)
344
lfd $N1,`$FRAME+104`($sp)
345
lfd $N2,`$FRAME+112`($sp)
346
lfd $N3,`$FRAME+120`($sp)
360
stfd $A0,8($nap_d) ; save a[j] in double format
364
stfd $A2,24($nap_d) ; save a[j+1] in double format
368
stfd $N0,40($nap_d) ; save n[j] in double format
372
stfd $N2,56($nap_d) ; save n[j+1] in double format
375
fmadd $T1a,$A0,$bc,$T1a
376
fmadd $T1b,$A0,$bd,$T1b
377
fmadd $T2a,$A1,$bc,$T2a
378
fmadd $T2b,$A1,$bd,$T2b
379
fmadd $T3a,$A2,$bc,$T3a
380
fmadd $T3b,$A2,$bd,$T3b
384
fmadd $T1a,$N1,$na,$T1a
385
fmadd $T1b,$N1,$nb,$T1b
386
fmadd $T2a,$N2,$na,$T2a
387
fmadd $T2b,$N2,$nb,$T2b
388
fmadd $T3a,$N3,$na,$T3a
389
fmadd $T3b,$N3,$nb,$T3b
390
fmadd $T0a,$N0,$na,$T0a
391
fmadd $T0b,$N0,$nb,$T0b
393
fmadd $T1a,$N0,$nc,$T1a
394
fmadd $T1b,$N0,$nd,$T1b
395
fmadd $T2a,$N1,$nc,$T2a
396
fmadd $T2b,$N1,$nd,$T2b
397
fmadd $T3a,$N2,$nc,$T3a
398
fmadd $T3b,$N2,$nd,$T3b
399
fmadd $dota,$N3,$nc,$dota
400
fmadd $dotb,$N3,$nd,$dotb
411
stfd $T0a,`$FRAME+0`($sp)
412
stfd $T0b,`$FRAME+8`($sp)
413
stfd $T1a,`$FRAME+16`($sp)
414
stfd $T1b,`$FRAME+24`($sp)
415
stfd $T2a,`$FRAME+32`($sp)
416
stfd $T2b,`$FRAME+40`($sp)
417
stfd $T3a,`$FRAME+48`($sp)
418
stfd $T3b,`$FRAME+56`($sp)
423
$code.=<<___ if ($SIZE_T==8);
424
lwz $t0,4($ap) ; load a[j] as 32-bit word pair
426
lwz $t2,12($ap) ; load a[j+1] as 32-bit word pair
428
lwz $t4,4($np) ; load n[j] as 32-bit word pair
430
lwz $t6,12($np) ; load n[j+1] as 32-bit word pair
433
$code.=<<___ if ($SIZE_T==4);
434
lwz $t0,0($ap) ; load a[j..j+3] as 32-bit word pairs
438
lwz $t4,0($np) ; load n[j..j+3] as 32-bit word pairs
444
std $t0,`$FRAME+64`($sp)
445
std $t1,`$FRAME+72`($sp)
446
std $t2,`$FRAME+80`($sp)
447
std $t3,`$FRAME+88`($sp)
448
std $t4,`$FRAME+96`($sp)
449
std $t5,`$FRAME+104`($sp)
450
std $t6,`$FRAME+112`($sp)
451
std $t7,`$FRAME+120`($sp)
452
ld $t0,`$FRAME+0`($sp)
453
ld $t1,`$FRAME+8`($sp)
454
ld $t2,`$FRAME+16`($sp)
455
ld $t3,`$FRAME+24`($sp)
456
ld $t4,`$FRAME+32`($sp)
457
ld $t5,`$FRAME+40`($sp)
458
ld $t6,`$FRAME+48`($sp)
459
ld $t7,`$FRAME+56`($sp)
460
lfd $A0,`$FRAME+64`($sp)
461
lfd $A1,`$FRAME+72`($sp)
462
lfd $A2,`$FRAME+80`($sp)
463
lfd $A3,`$FRAME+88`($sp)
464
lfd $N0,`$FRAME+96`($sp)
465
lfd $N1,`$FRAME+104`($sp)
466
lfd $N2,`$FRAME+112`($sp)
467
lfd $N3,`$FRAME+120`($sp)
483
stfd $A0,8($nap_d) ; save a[j] in double format
487
fmadd $T0a,$A0,$ba,$dota
488
fmadd $T0b,$A0,$bb,$dotb
489
stfd $A2,24($nap_d) ; save a[j+1] in double format
492
fmadd $T1a,$A0,$bc,$T1a
493
fmadd $T1b,$A0,$bd,$T1b
494
fmadd $T2a,$A1,$bc,$T2a
495
fmadd $T2b,$A1,$bd,$T2b
496
stfd $N0,40($nap_d) ; save n[j] in double format
498
fmadd $T3a,$A2,$bc,$T3a
499
fmadd $T3b,$A2,$bd,$T3b
500
add $t0,$t0,$carry ; can not overflow
503
stfd $N2,56($nap_d) ; save n[j+1] in double format
509
fmadd $T1a,$N1,$na,$T1a
510
fmadd $T1b,$N1,$nb,$T1b
512
fmadd $T2a,$N2,$na,$T2a
513
fmadd $T2b,$N2,$nb,$T2b
515
fmadd $T3a,$N3,$na,$T3a
516
fmadd $T3b,$N3,$nb,$T3b
518
fmadd $T0a,$N0,$na,$T0a
519
fmadd $T0b,$N0,$nb,$T0b
524
fmadd $T1a,$N0,$nc,$T1a
525
fmadd $T1b,$N0,$nd,$T1b
526
insrdi $t0,$t3,16,0 ; 0..63 bits
527
fmadd $T2a,$N1,$nc,$T2a
528
fmadd $T2b,$N1,$nd,$T2b
530
fmadd $T3a,$N2,$nc,$T3a
531
fmadd $T3b,$N2,$nd,$T3b
533
fmadd $dota,$N3,$nc,$dota
534
fmadd $dotb,$N3,$nd,$dotb
551
insrdi $t4,$t7,16,0 ; 64..127 bits
552
srdi $carry,$t7,16 ; upper 33 bits
554
stfd $T0a,`$FRAME+0`($sp)
555
stfd $T0b,`$FRAME+8`($sp)
556
stfd $T1a,`$FRAME+16`($sp)
557
stfd $T1b,`$FRAME+24`($sp)
558
stfd $T2a,`$FRAME+32`($sp)
559
stfd $T2b,`$FRAME+40`($sp)
560
stfd $T3a,`$FRAME+48`($sp)
561
stfd $T3b,`$FRAME+56`($sp)
562
std $t0,8($tp) ; tp[j-1]
563
stdu $t4,16($tp) ; tp[j]
569
ld $t0,`$FRAME+0`($sp)
570
ld $t1,`$FRAME+8`($sp)
571
ld $t2,`$FRAME+16`($sp)
572
ld $t3,`$FRAME+24`($sp)
573
ld $t4,`$FRAME+32`($sp)
574
ld $t5,`$FRAME+40`($sp)
575
ld $t6,`$FRAME+48`($sp)
576
ld $t7,`$FRAME+56`($sp)
577
stfd $dota,`$FRAME+64`($sp)
578
stfd $dotb,`$FRAME+72`($sp)
580
add $t0,$t0,$carry ; can not overflow
590
insrdi $t0,$t3,16,0 ; 0..63 bits
600
insrdi $t4,$t7,16,0 ; 64..127 bits
601
srdi $carry,$t7,16 ; upper 33 bits
602
ld $t6,`$FRAME+64`($sp)
603
ld $t7,`$FRAME+72`($sp)
605
std $t0,8($tp) ; tp[j-1]
606
stdu $t4,16($tp) ; tp[j]
608
add $t6,$t6,$carry ; can not overflow
613
std $t6,8($tp) ; tp[num-1]
616
subf $nap_d,$t7,$nap_d ; rewind pointer
622
$code.=<<___ if ($SIZE_T==8);
623
ldx $t3,$bp,$i ; bp[i]
625
$code.=<<___ if ($SIZE_T==4);
627
lwz $t3,0($t0) ; bp[i,i+1]
632
ld $t6,`$FRAME+$TRANSFER+8`($sp) ; tp[0]
633
mulld $t7,$a0,$t3 ; ap[0]*bp[i]
635
addi $tp,$sp,`$FRAME+$TRANSFER`
636
add $t7,$t7,$t6 ; ap[0]*bp[i]+tp[0]
638
mulld $t7,$t7,$n0 ; tp[0]*n0
641
; transfer bp[i] to FPU as 4x16-bit values
646
std $t0,`$FRAME+0`($sp)
647
std $t1,`$FRAME+8`($sp)
648
std $t2,`$FRAME+16`($sp)
649
std $t3,`$FRAME+24`($sp)
650
; transfer (ap[0]*bp[i]+tp[0])*n0 to FPU as 4x16-bit values
655
std $t4,`$FRAME+32`($sp)
656
std $t5,`$FRAME+40`($sp)
657
std $t6,`$FRAME+48`($sp)
658
std $t7,`$FRAME+56`($sp)
660
lfd $A0,8($nap_d) ; load a[j] in double format
662
lfd $A2,24($nap_d) ; load a[j+1] in double format
664
lfd $N0,40($nap_d) ; load n[j] in double format
666
lfd $N2,56($nap_d) ; load n[j+1] in double format
669
lfd $ba,`$FRAME+0`($sp)
670
lfd $bb,`$FRAME+8`($sp)
671
lfd $bc,`$FRAME+16`($sp)
672
lfd $bd,`$FRAME+24`($sp)
673
lfd $na,`$FRAME+32`($sp)
674
lfd $nb,`$FRAME+40`($sp)
675
lfd $nc,`$FRAME+48`($sp)
676
lfd $nd,`$FRAME+56`($sp)
696
fmadd $T1a,$A0,$bc,$T1a
697
fmadd $T1b,$A0,$bd,$T1b
698
fmadd $T2a,$A1,$bc,$T2a
699
fmadd $T2b,$A1,$bd,$T2b
700
fmadd $T3a,$A2,$bc,$T3a
701
fmadd $T3b,$A2,$bd,$T3b
705
fmadd $T1a,$N1,$na,$T1a
706
fmadd $T1b,$N1,$nb,$T1b
707
lfd $A0,8($nap_d) ; load a[j] in double format
709
fmadd $T2a,$N2,$na,$T2a
710
fmadd $T2b,$N2,$nb,$T2b
711
lfd $A2,24($nap_d) ; load a[j+1] in double format
713
fmadd $T3a,$N3,$na,$T3a
714
fmadd $T3b,$N3,$nb,$T3b
715
fmadd $T0a,$N0,$na,$T0a
716
fmadd $T0b,$N0,$nb,$T0b
718
fmadd $T1a,$N0,$nc,$T1a
719
fmadd $T1b,$N0,$nd,$T1b
720
fmadd $T2a,$N1,$nc,$T2a
721
fmadd $T2b,$N1,$nd,$T2b
722
fmadd $T3a,$N2,$nc,$T3a
723
fmadd $T3b,$N2,$nd,$T3b
724
fmadd $dota,$N3,$nc,$dota
725
fmadd $dotb,$N3,$nd,$dotb
736
stfd $T0a,`$FRAME+0`($sp)
737
stfd $T0b,`$FRAME+8`($sp)
738
stfd $T1a,`$FRAME+16`($sp)
739
stfd $T1b,`$FRAME+24`($sp)
740
stfd $T2a,`$FRAME+32`($sp)
741
stfd $T2b,`$FRAME+40`($sp)
742
stfd $T3a,`$FRAME+48`($sp)
743
stfd $T3b,`$FRAME+56`($sp)
751
lfd $N0,40($nap_d) ; load n[j] in double format
755
fmadd $T0a,$A0,$ba,$dota
756
fmadd $T0b,$A0,$bb,$dotb
757
lfd $N2,56($nap_d) ; load n[j+1] in double format
760
fmadd $T1a,$A0,$bc,$T1a
761
fmadd $T1b,$A0,$bd,$T1b
762
fmadd $T2a,$A1,$bc,$T2a
763
fmadd $T2b,$A1,$bd,$T2b
764
lfd $A0,8($nap_d) ; load a[j] in double format
766
fmadd $T3a,$A2,$bc,$T3a
767
fmadd $T3b,$A2,$bd,$T3b
770
lfd $A2,24($nap_d) ; load a[j+1] in double format
773
fmadd $T1a,$N1,$na,$T1a
774
fmadd $T1b,$N1,$nb,$T1b
775
ld $t0,`$FRAME+0`($sp)
776
ld $t1,`$FRAME+8`($sp)
777
fmadd $T2a,$N2,$na,$T2a
778
fmadd $T2b,$N2,$nb,$T2b
779
ld $t2,`$FRAME+16`($sp)
780
ld $t3,`$FRAME+24`($sp)
781
fmadd $T3a,$N3,$na,$T3a
782
fmadd $T3b,$N3,$nb,$T3b
783
add $t0,$t0,$carry ; can not overflow
784
ld $t4,`$FRAME+32`($sp)
785
ld $t5,`$FRAME+40`($sp)
786
fmadd $T0a,$N0,$na,$T0a
787
fmadd $T0b,$N0,$nb,$T0b
791
ld $t6,`$FRAME+48`($sp)
792
ld $t7,`$FRAME+56`($sp)
794
fmadd $T1a,$N0,$nc,$T1a
795
fmadd $T1b,$N0,$nd,$T1b
797
ld $t1,8($tp) ; tp[j]
798
fmadd $T2a,$N1,$nc,$T2a
799
fmadd $T2b,$N1,$nd,$T2b
801
fmadd $T3a,$N2,$nc,$T3a
802
fmadd $T3b,$N2,$nd,$T3b
805
fmadd $dota,$N3,$nc,$dota
806
fmadd $dotb,$N3,$nd,$dotb
808
ldu $t2,16($tp) ; tp[j+1]
810
insrdi $t0,$t3,16,0 ; 0..63 bits
829
stfd $T0a,`$FRAME+0`($sp)
830
stfd $T0b,`$FRAME+8`($sp)
834
$code.=<<___ if ($SIZE_T==4); # adjust XER[CA]
840
stfd $T1a,`$FRAME+16`($sp)
841
stfd $T1b,`$FRAME+24`($sp)
842
insrdi $t4,$t7,16,0 ; 64..127 bits
843
srdi $carry,$t7,16 ; upper 33 bits
844
stfd $T2a,`$FRAME+32`($sp)
845
stfd $T2b,`$FRAME+40`($sp)
848
$code.=<<___ if ($SIZE_T==4); # adjust XER[CA]
854
stfd $T3a,`$FRAME+48`($sp)
855
stfd $T3b,`$FRAME+56`($sp)
857
std $t3,-16($tp) ; tp[j-1]
858
std $t5,-8($tp) ; tp[j]
863
ld $t0,`$FRAME+0`($sp)
864
ld $t1,`$FRAME+8`($sp)
865
ld $t2,`$FRAME+16`($sp)
866
ld $t3,`$FRAME+24`($sp)
867
ld $t4,`$FRAME+32`($sp)
868
ld $t5,`$FRAME+40`($sp)
869
ld $t6,`$FRAME+48`($sp)
870
ld $t7,`$FRAME+56`($sp)
871
stfd $dota,`$FRAME+64`($sp)
872
stfd $dotb,`$FRAME+72`($sp)
874
add $t0,$t0,$carry ; can not overflow
880
ld $t1,8($tp) ; tp[j]
884
ldu $t2,16($tp) ; tp[j+1]
886
insrdi $t0,$t3,16,0 ; 0..63 bits
896
insrdi $t4,$t7,16,0 ; 64..127 bits
897
srdi $carry,$t7,16 ; upper 33 bits
898
ld $t6,`$FRAME+64`($sp)
899
ld $t7,`$FRAME+72`($sp)
903
$code.=<<___ if ($SIZE_T==4); # adjust XER[CA]
911
$code.=<<___ if ($SIZE_T==4); # adjust XER[CA]
919
std $t3,-16($tp) ; tp[j-1]
920
std $t5,-8($tp) ; tp[j]
922
add $carry,$carry,$ovf ; comsume upmost overflow
923
add $t6,$t6,$carry ; can not overflow
928
std $t6,0($tp) ; tp[num-1]
932
subf $nap_d,$t7,$nap_d ; rewind pointer
937
$code.=<<___ if ($SIZE_T==8);
938
subf $np,$num,$np ; rewind np
939
addi $j,$j,1 ; restore counter
940
subfc $i,$i,$i ; j=0 and "clear" XER[CA]
941
addi $tp,$sp,`$FRAME+$TRANSFER+8`
942
addi $t4,$sp,`$FRAME+$TRANSFER+16`
952
subfe $t0,$t1,$t0 ; tp[j]-np[j]
953
subfe $t2,$t3,$t2 ; tp[j+1]-np[j+1]
960
subfe $ovf,$i,$ovf ; handle upmost overflow bit
963
or $ap,$ap,$np ; ap=borrow?tp:rp
968
Lcopy: ; copy or in-place refresh
971
std $i,8($nap_d) ; zap nap_d
981
stdx $i,$tp,$i ; zap tp at once
986
$code.=<<___ if ($SIZE_T==4);
987
subf $np,$num,$np ; rewind np
988
addi $j,$j,1 ; restore counter
989
subfc $i,$i,$i ; j=0 and "clear" XER[CA]
990
addi $tp,$sp,`$FRAME+$TRANSFER`
993
addi $ap,$sp,`$FRAME+$TRANSFER+4`
997
Lsub: ld $t0,8($tp) ; load tp[j..j+3] in 64-bit word order
999
lwz $t4,4($np) ; load np[j..j+3] in 32-bit word order
1005
subfe $t4,$t4,$t0 ; tp[j]-np[j]
1006
stw $t0,4($ap) ; save tp[j..j+3] in 32-bit word order
1007
subfe $t5,$t5,$t1 ; tp[j+1]-np[j+1]
1009
subfe $t6,$t6,$t2 ; tp[j+2]-np[j+2]
1011
subfe $t7,$t7,$t3 ; tp[j+3]-np[j+3]
1020
subfe $ovf,$i,$ovf ; handle upmost overflow bit
1021
addi $tp,$sp,`$FRAME+$TRANSFER+4`
1022
subf $rp,$num,$rp ; rewind rp
1025
or $ap,$ap,$np ; ap=borrow?tp:rp
1026
addi $tp,$sp,`$FRAME+$TRANSFER`
1030
Lcopy: ; copy or in-place refresh
1035
std $i,8($nap_d) ; zap nap_d
1047
std $i,8($tp) ; zap tp at once
1054
li r3,1 ; signal "handled"
1055
$POP r22,`-12*8-10*$SIZE_T`($i)
1056
$POP r23,`-12*8-9*$SIZE_T`($i)
1057
$POP r24,`-12*8-8*$SIZE_T`($i)
1058
$POP r25,`-12*8-7*$SIZE_T`($i)
1059
$POP r26,`-12*8-6*$SIZE_T`($i)
1060
$POP r27,`-12*8-5*$SIZE_T`($i)
1061
$POP r28,`-12*8-4*$SIZE_T`($i)
1062
$POP r29,`-12*8-3*$SIZE_T`($i)
1063
$POP r30,`-12*8-2*$SIZE_T`($i)
1064
$POP r31,`-12*8-1*$SIZE_T`($i)
1080
.byte 0,12,4,0,0x8c,10,6,0
1083
.asciz "Montgomery Multiplication for PPC64, CRYPTOGAMS by <appro\@openssl.org>"
1086
$code =~ s/\`([^\`]*)\`/eval $1/gem;