fc2f354cfc7929e7cda1dbe4023b93d5a4228026
[openssl.git] / crypto / bn / asm / ppc64-mont.pl
1 #!/usr/bin/env perl
2
3 # ====================================================================
4 # Written by Andy Polyakov <appro@fy.chalmers.se> for the OpenSSL
5 # project. The module is, however, dual licensed under OpenSSL and
6 # CRYPTOGAMS licenses depending on where you obtain it. For further
7 # details see http://www.openssl.org/~appro/cryptogams/.
8 # ====================================================================
9
10 # December 2007
11
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.
37
38 # February 2008
39
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...
47
48 # December 2009
49
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...
67
68 $flavour = shift;
69
70 if ($flavour =~ /32/) {
71         $SIZE_T=4;
72         $RZONE= 224;
73         $fname= "bn_mul_mont_fpu64";
74
75         $STUX=  "stwux";        # store indexed and update
76         $PUSH=  "stw";
77         $POP=   "lwz";
78 } elsif ($flavour =~ /64/) {
79         $SIZE_T=8;
80         $RZONE= 288;
81         $fname= "bn_mul_mont_fpu64";
82
83         # same as above, but 64-bit mnemonics...
84         $STUX=  "stdux";        # store indexed and update
85         $PUSH=  "std";
86         $POP=   "ld";
87 } else { die "nonsense $flavour"; }
88
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";
93
94 open STDOUT,"| $^X $xlate $flavour ".shift || die "can't call $xlate: $!";
95
96 $FRAME=64;      # padded frame header
97 $TRANSFER=16*8;
98
99 $carry="r0";
100 $sp="r1";
101 $toc="r2";
102 $rp="r3";       $ovf="r3";
103 $ap="r4";
104 $bp="r5";
105 $np="r6";
106 $n0="r7";
107 $num="r8";
108 $rp="r9";       # $rp is reassigned
109 $tp="r10";
110 $j="r11";
111 $i="r12";
112 # non-volatile registers
113 $nap_d="r22";   # interleaved ap and np in double format
114 $a0="r23";      # ap[0]
115 $t0="r24";      # temporary registers
116 $t1="r25";
117 $t2="r26";
118 $t3="r27";
119 $t4="r28";
120 $t5="r29";
121 $t6="r30";
122 $t7="r31";
123
124 # PPC offers enough register bank capacity to unroll inner loops twice
125 #
126 #     ..A3A2A1A0
127 #           dcba
128 #    -----------
129 #            A0a
130 #           A0b
131 #          A0c
132 #         A0d
133 #          A1a
134 #         A1b
135 #        A1c
136 #       A1d
137 #        A2a
138 #       A2b
139 #      A2c
140 #     A2d
141 #      A3a
142 #     A3b
143 #    A3c
144 #   A3d
145 #    ..a
146 #   ..b
147 #
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";
157 \f
158 # sp----------->+-------------------------------+
159 #               | saved sp                      |
160 #               +-------------------------------+
161 #               .                               .
162 #   +64         +-------------------------------+
163 #               | 16 gpr<->fpr transfer zone    |
164 #               .                               .
165 #               .                               .
166 #   +16*8       +-------------------------------+
167 #               | __int64 tmp[-1]               |
168 #               +-------------------------------+
169 #               | __int64 tmp[num]              |
170 #               .                               .
171 #               .                               .
172 #               .                               .
173 #   +(num+1)*8  +-------------------------------+
174 #               | padding to 64 byte boundary   |
175 #               .                               .
176 #   +X          +-------------------------------+
177 #               | double nap_d[4*num]           |
178 #               .                               .
179 #               .                               .
180 #               .                               .
181 #               +-------------------------------+
182 #               .                               .
183 #   -12*size_t  +-------------------------------+
184 #               | 10 saved gpr, r22-r31         |
185 #               .                               .
186 #               .                               .
187 #   -12*8       +-------------------------------+
188 #               | 12 saved fpr, f20-f31         |
189 #               .                               .
190 #               .                               .
191 #               +-------------------------------+
192 \f
193 $code=<<___;
194 .machine "any"
195 .text
196
197 .globl  .$fname
198 .align  5
199 .$fname:
200         cmpwi   $num,`3*8/$SIZE_T`
201         mr      $rp,r3          ; $rp is reassigned
202         li      r3,0            ; possible "not handled" return code
203         bltlr-
204         andi.   r0,$num,`16/$SIZE_T-1`          ; $num has to be "even"
205         bnelr-
206
207         slwi    $num,$num,`log($SIZE_T)/log(2)` ; num*=sizeof(BN_LONG)
208         li      $i,-4096
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
215         mr      $i,$sp
216         $STUX   $sp,$sp,$tp     ; alloca
217
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)
228         stfd    f20,`-12*8`($i)
229         stfd    f21,`-11*8`($i)
230         stfd    f22,`-10*8`($i)
231         stfd    f23,`-9*8`($i)
232         stfd    f24,`-8*8`($i)
233         stfd    f25,`-7*8`($i)
234         stfd    f26,`-6*8`($i)
235         stfd    f27,`-5*8`($i)
236         stfd    f28,`-4*8`($i)
237         stfd    f29,`-3*8`($i)
238         stfd    f30,`-2*8`($i)
239         stfd    f31,`-1*8`($i)
240 ___
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]
245 ___
246 $code.=<<___ if ($SIZE_T==4);
247         mr      $t1,$n0
248         lwz     $a0,0($ap)      ; pull ap[0,1] value
249         lwz     $t0,4($ap)
250         lwz     $n0,0($t1)      ; pull n0[0,1] value
251         lwz     $t1,4($t1)
252         lwz     $t3,0($bp)      ; bp[0,1]
253         lwz     $t2,4($bp)
254         insrdi  $a0,$t0,32,0
255         insrdi  $n0,$t1,32,0
256         insrdi  $t3,$t2,32,0
257 ___
258 $code.=<<___;
259         addi    $tp,$sp,`$FRAME+$TRANSFER+8+64`
260         li      $i,-64
261         add     $nap_d,$tp,$num
262         and     $nap_d,$nap_d,$i        ; align to 64 bytes
263 \f
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
269         addi    $j,$j,-1
270         addi    $tp,$sp,`$FRAME+$TRANSFER-8`
271         li      $carry,0
272         mtctr   $j
273
274         ; transfer bp[0] to FPU as 4x16-bit values
275         extrdi  $t0,$t3,16,48
276         extrdi  $t1,$t3,16,32
277         extrdi  $t2,$t3,16,16
278         extrdi  $t3,$t3,16,0
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
284         extrdi  $t4,$t7,16,48
285         extrdi  $t5,$t7,16,32
286         extrdi  $t6,$t7,16,16
287         extrdi  $t7,$t7,16,0
288         std     $t4,`$FRAME+32`($sp)
289         std     $t5,`$FRAME+40`($sp)
290         std     $t6,`$FRAME+48`($sp)
291         std     $t7,`$FRAME+56`($sp)
292 ___
293 $code.=<<___ if ($SIZE_T==8);
294         lwz     $t0,4($ap)              ; load a[j] as 32-bit word pair
295         lwz     $t1,0($ap)
296         lwz     $t2,12($ap)             ; load a[j+1] as 32-bit word pair
297         lwz     $t3,8($ap)
298         lwz     $t4,4($np)              ; load n[j] as 32-bit word pair
299         lwz     $t5,0($np)
300         lwz     $t6,12($np)             ; load n[j+1] as 32-bit word pair
301         lwz     $t7,8($np)
302 ___
303 $code.=<<___ if ($SIZE_T==4);
304         lwz     $t0,0($ap)              ; load a[j..j+3] as 32-bit word pairs
305         lwz     $t1,4($ap)
306         lwz     $t2,8($ap)
307         lwz     $t3,12($ap)
308         lwz     $t4,0($np)              ; load n[j..j+3] as 32-bit word pairs
309         lwz     $t5,4($np)
310         lwz     $t6,8($np)
311         lwz     $t7,12($np)
312 ___
313 $code.=<<___;
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)
330         fcfid   $ba,$ba
331         fcfid   $bb,$bb
332         fcfid   $bc,$bc
333         fcfid   $bd,$bd
334         fcfid   $na,$na
335         fcfid   $nb,$nb
336         fcfid   $nc,$nc
337         fcfid   $nd,$nd
338
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)
347         fcfid   $A0,$A0
348         fcfid   $A1,$A1
349         fcfid   $A2,$A2
350         fcfid   $A3,$A3
351         fcfid   $N0,$N0
352         fcfid   $N1,$N1
353         fcfid   $N2,$N2
354         fcfid   $N3,$N3
355         addi    $ap,$ap,16
356         addi    $np,$np,16
357
358         fmul    $T1a,$A1,$ba
359         fmul    $T1b,$A1,$bb
360         stfd    $A0,8($nap_d)           ; save a[j] in double format
361         stfd    $A1,16($nap_d)
362         fmul    $T2a,$A2,$ba
363         fmul    $T2b,$A2,$bb
364         stfd    $A2,24($nap_d)          ; save a[j+1] in double format
365         stfd    $A3,32($nap_d)
366         fmul    $T3a,$A3,$ba
367         fmul    $T3b,$A3,$bb
368         stfd    $N0,40($nap_d)          ; save n[j] in double format
369         stfd    $N1,48($nap_d)
370         fmul    $T0a,$A0,$ba
371         fmul    $T0b,$A0,$bb
372         stfd    $N2,56($nap_d)          ; save n[j+1] in double format
373         stfdu   $N3,64($nap_d)
374
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
381         fmul    $dota,$A3,$bc
382         fmul    $dotb,$A3,$bd
383
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
392
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
401
402         fctid   $T0a,$T0a
403         fctid   $T0b,$T0b
404         fctid   $T1a,$T1a
405         fctid   $T1b,$T1b
406         fctid   $T2a,$T2a
407         fctid   $T2b,$T2b
408         fctid   $T3a,$T3a
409         fctid   $T3b,$T3b
410
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)
419 \f
420 .align  5
421 L1st:
422 ___
423 $code.=<<___ if ($SIZE_T==8);
424         lwz     $t0,4($ap)              ; load a[j] as 32-bit word pair
425         lwz     $t1,0($ap)
426         lwz     $t2,12($ap)             ; load a[j+1] as 32-bit word pair
427         lwz     $t3,8($ap)
428         lwz     $t4,4($np)              ; load n[j] as 32-bit word pair
429         lwz     $t5,0($np)
430         lwz     $t6,12($np)             ; load n[j+1] as 32-bit word pair
431         lwz     $t7,8($np)
432 ___
433 $code.=<<___ if ($SIZE_T==4);
434         lwz     $t0,0($ap)              ; load a[j..j+3] as 32-bit word pairs
435         lwz     $t1,4($ap)
436         lwz     $t2,8($ap)
437         lwz     $t3,12($ap)
438         lwz     $t4,0($np)              ; load n[j..j+3] as 32-bit word pairs
439         lwz     $t5,4($np)
440         lwz     $t6,8($np)
441         lwz     $t7,12($np)
442 ___
443 $code.=<<___;
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)
468         fcfid   $A0,$A0
469         fcfid   $A1,$A1
470         fcfid   $A2,$A2
471         fcfid   $A3,$A3
472         fcfid   $N0,$N0
473         fcfid   $N1,$N1
474         fcfid   $N2,$N2
475         fcfid   $N3,$N3
476         addi    $ap,$ap,16
477         addi    $np,$np,16
478
479         fmul    $T1a,$A1,$ba
480         fmul    $T1b,$A1,$bb
481         fmul    $T2a,$A2,$ba
482         fmul    $T2b,$A2,$bb
483         stfd    $A0,8($nap_d)           ; save a[j] in double format
484         stfd    $A1,16($nap_d)
485         fmul    $T3a,$A3,$ba
486         fmul    $T3b,$A3,$bb
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
490         stfd    $A3,32($nap_d)
491
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
497         stfd    $N1,48($nap_d)
498         fmadd   $T3a,$A2,$bc,$T3a
499         fmadd   $T3b,$A2,$bd,$T3b
500          add    $t0,$t0,$carry          ; can not overflow
501         fmul    $dota,$A3,$bc
502         fmul    $dotb,$A3,$bd
503         stfd    $N2,56($nap_d)          ; save n[j+1] in double format
504         stfdu   $N3,64($nap_d)
505          srdi   $carry,$t0,16
506          add    $t1,$t1,$carry
507          srdi   $carry,$t1,16
508
509         fmadd   $T1a,$N1,$na,$T1a
510         fmadd   $T1b,$N1,$nb,$T1b
511          insrdi $t0,$t1,16,32
512         fmadd   $T2a,$N2,$na,$T2a
513         fmadd   $T2b,$N2,$nb,$T2b
514          add    $t2,$t2,$carry
515         fmadd   $T3a,$N3,$na,$T3a
516         fmadd   $T3b,$N3,$nb,$T3b
517          srdi   $carry,$t2,16
518         fmadd   $T0a,$N0,$na,$T0a
519         fmadd   $T0b,$N0,$nb,$T0b
520          insrdi $t0,$t2,16,16
521          add    $t3,$t3,$carry
522          srdi   $carry,$t3,16
523
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
529          add    $t4,$t4,$carry
530         fmadd   $T3a,$N2,$nc,$T3a
531         fmadd   $T3b,$N2,$nd,$T3b
532          srdi   $carry,$t4,16
533         fmadd   $dota,$N3,$nc,$dota
534         fmadd   $dotb,$N3,$nd,$dotb
535          add    $t5,$t5,$carry
536          srdi   $carry,$t5,16
537          insrdi $t4,$t5,16,32
538
539         fctid   $T0a,$T0a
540         fctid   $T0b,$T0b
541          add    $t6,$t6,$carry
542         fctid   $T1a,$T1a
543         fctid   $T1b,$T1b
544          srdi   $carry,$t6,16
545         fctid   $T2a,$T2a
546         fctid   $T2b,$T2b
547          insrdi $t4,$t6,16,16
548         fctid   $T3a,$T3a
549         fctid   $T3b,$T3b
550          add    $t7,$t7,$carry
551          insrdi $t4,$t7,16,0            ; 64..127 bits
552          srdi   $carry,$t7,16           ; upper 33 bits
553
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]
564         bdnz-   L1st
565 \f
566         fctid   $dota,$dota
567         fctid   $dotb,$dotb
568
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)
579
580         add     $t0,$t0,$carry          ; can not overflow
581         srdi    $carry,$t0,16
582         add     $t1,$t1,$carry
583         srdi    $carry,$t1,16
584         insrdi  $t0,$t1,16,32
585         add     $t2,$t2,$carry
586         srdi    $carry,$t2,16
587         insrdi  $t0,$t2,16,16
588         add     $t3,$t3,$carry
589         srdi    $carry,$t3,16
590         insrdi  $t0,$t3,16,0            ; 0..63 bits
591         add     $t4,$t4,$carry
592         srdi    $carry,$t4,16
593         add     $t5,$t5,$carry
594         srdi    $carry,$t5,16
595         insrdi  $t4,$t5,16,32
596         add     $t6,$t6,$carry
597         srdi    $carry,$t6,16
598         insrdi  $t4,$t6,16,16
599         add     $t7,$t7,$carry
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)
604
605         std     $t0,8($tp)              ; tp[j-1]
606         stdu    $t4,16($tp)             ; tp[j]
607
608         add     $t6,$t6,$carry          ; can not overflow
609         srdi    $carry,$t6,16
610         add     $t7,$t7,$carry
611         insrdi  $t6,$t7,48,0
612         srdi    $ovf,$t7,48
613         std     $t6,8($tp)              ; tp[num-1]
614
615         slwi    $t7,$num,2
616         subf    $nap_d,$t7,$nap_d       ; rewind pointer
617 \f
618         li      $i,8                    ; i=1
619 .align  5
620 Louter:
621 ___
622 $code.=<<___ if ($SIZE_T==8);
623         ldx     $t3,$bp,$i      ; bp[i]
624 ___
625 $code.=<<___ if ($SIZE_T==4);
626         add     $t0,$bp,$i
627         lwz     $t3,0($t0)              ; bp[i,i+1]
628         lwz     $t0,4($t0)
629         insrdi  $t3,$t0,32,0
630 ___
631 $code.=<<___;
632         ld      $t6,`$FRAME+$TRANSFER+8`($sp)   ; tp[0]
633         mulld   $t7,$a0,$t3     ; ap[0]*bp[i]
634
635         addi    $tp,$sp,`$FRAME+$TRANSFER`
636         add     $t7,$t7,$t6     ; ap[0]*bp[i]+tp[0]
637         li      $carry,0
638         mulld   $t7,$t7,$n0     ; tp[0]*n0
639         mtctr   $j
640
641         ; transfer bp[i] to FPU as 4x16-bit values
642         extrdi  $t0,$t3,16,48
643         extrdi  $t1,$t3,16,32
644         extrdi  $t2,$t3,16,16
645         extrdi  $t3,$t3,16,0
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
651         extrdi  $t4,$t7,16,48
652         extrdi  $t5,$t7,16,32
653         extrdi  $t6,$t7,16,16
654         extrdi  $t7,$t7,16,0
655         std     $t4,`$FRAME+32`($sp)
656         std     $t5,`$FRAME+40`($sp)
657         std     $t6,`$FRAME+48`($sp)
658         std     $t7,`$FRAME+56`($sp)
659
660         lfd     $A0,8($nap_d)           ; load a[j] in double format
661         lfd     $A1,16($nap_d)
662         lfd     $A2,24($nap_d)          ; load a[j+1] in double format
663         lfd     $A3,32($nap_d)
664         lfd     $N0,40($nap_d)          ; load n[j] in double format
665         lfd     $N1,48($nap_d)
666         lfd     $N2,56($nap_d)          ; load n[j+1] in double format
667         lfdu    $N3,64($nap_d)
668
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)
677
678         fcfid   $ba,$ba
679         fcfid   $bb,$bb
680         fcfid   $bc,$bc
681         fcfid   $bd,$bd
682         fcfid   $na,$na
683         fcfid   $nb,$nb
684         fcfid   $nc,$nc
685         fcfid   $nd,$nd
686
687         fmul    $T1a,$A1,$ba
688         fmul    $T1b,$A1,$bb
689         fmul    $T2a,$A2,$ba
690         fmul    $T2b,$A2,$bb
691         fmul    $T3a,$A3,$ba
692         fmul    $T3b,$A3,$bb
693         fmul    $T0a,$A0,$ba
694         fmul    $T0b,$A0,$bb
695
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
702         fmul    $dota,$A3,$bc
703         fmul    $dotb,$A3,$bd
704
705         fmadd   $T1a,$N1,$na,$T1a
706         fmadd   $T1b,$N1,$nb,$T1b
707          lfd    $A0,8($nap_d)           ; load a[j] in double format
708          lfd    $A1,16($nap_d)
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
712          lfd    $A3,32($nap_d)
713         fmadd   $T3a,$N3,$na,$T3a
714         fmadd   $T3b,$N3,$nb,$T3b
715         fmadd   $T0a,$N0,$na,$T0a
716         fmadd   $T0b,$N0,$nb,$T0b
717
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
726
727         fctid   $T0a,$T0a
728         fctid   $T0b,$T0b
729         fctid   $T1a,$T1a
730         fctid   $T1b,$T1b
731         fctid   $T2a,$T2a
732         fctid   $T2b,$T2b
733         fctid   $T3a,$T3a
734         fctid   $T3b,$T3b
735
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)
744 \f
745 .align  5
746 Linner:
747         fmul    $T1a,$A1,$ba
748         fmul    $T1b,$A1,$bb
749         fmul    $T2a,$A2,$ba
750         fmul    $T2b,$A2,$bb
751         lfd     $N0,40($nap_d)          ; load n[j] in double format
752         lfd     $N1,48($nap_d)
753         fmul    $T3a,$A3,$ba
754         fmul    $T3b,$A3,$bb
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
758         lfdu    $N3,64($nap_d)
759
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
765          lfd    $A1,16($nap_d)
766         fmadd   $T3a,$A2,$bc,$T3a
767         fmadd   $T3b,$A2,$bd,$T3b
768         fmul    $dota,$A3,$bc
769         fmul    $dotb,$A3,$bd
770          lfd    $A2,24($nap_d)          ; load a[j+1] in double format
771          lfd    $A3,32($nap_d)
772
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
788          srdi   $carry,$t0,16
789          add    $t1,$t1,$carry
790          srdi   $carry,$t1,16
791          ld     $t6,`$FRAME+48`($sp)
792          ld     $t7,`$FRAME+56`($sp)
793
794         fmadd   $T1a,$N0,$nc,$T1a
795         fmadd   $T1b,$N0,$nd,$T1b
796          insrdi $t0,$t1,16,32
797          ld     $t1,8($tp)              ; tp[j]
798         fmadd   $T2a,$N1,$nc,$T2a
799         fmadd   $T2b,$N1,$nd,$T2b
800          add    $t2,$t2,$carry
801         fmadd   $T3a,$N2,$nc,$T3a
802         fmadd   $T3b,$N2,$nd,$T3b
803          srdi   $carry,$t2,16
804          insrdi $t0,$t2,16,16
805         fmadd   $dota,$N3,$nc,$dota
806         fmadd   $dotb,$N3,$nd,$dotb
807          add    $t3,$t3,$carry
808          ldu    $t2,16($tp)             ; tp[j+1]
809          srdi   $carry,$t3,16
810          insrdi $t0,$t3,16,0            ; 0..63 bits
811          add    $t4,$t4,$carry
812
813         fctid   $T0a,$T0a
814         fctid   $T0b,$T0b
815          srdi   $carry,$t4,16
816         fctid   $T1a,$T1a
817         fctid   $T1b,$T1b
818          add    $t5,$t5,$carry
819         fctid   $T2a,$T2a
820         fctid   $T2b,$T2b
821          srdi   $carry,$t5,16
822          insrdi $t4,$t5,16,32
823         fctid   $T3a,$T3a
824         fctid   $T3b,$T3b
825          add    $t6,$t6,$carry
826          srdi   $carry,$t6,16
827          insrdi $t4,$t6,16,16
828
829         stfd    $T0a,`$FRAME+0`($sp)
830         stfd    $T0b,`$FRAME+8`($sp)
831          add    $t7,$t7,$carry
832          addc   $t3,$t0,$t1
833 ___
834 $code.=<<___ if ($SIZE_T==4);           # adjust XER[CA]
835         extrdi  $t0,$t0,32,0
836         extrdi  $t1,$t1,32,0
837         adde    $t0,$t0,$t1
838 ___
839 $code.=<<___;
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)
846          adde   $t5,$t4,$t2
847 ___
848 $code.=<<___ if ($SIZE_T==4);           # adjust XER[CA]
849         extrdi  $t4,$t4,32,0
850         extrdi  $t2,$t2,32,0
851         adde    $t4,$t4,$t2
852 ___
853 $code.=<<___;
854         stfd    $T3a,`$FRAME+48`($sp)
855         stfd    $T3b,`$FRAME+56`($sp)
856          addze  $carry,$carry
857          std    $t3,-16($tp)            ; tp[j-1]
858          std    $t5,-8($tp)             ; tp[j]
859         bdnz-   Linner
860 \f
861         fctid   $dota,$dota
862         fctid   $dotb,$dotb
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)
873
874         add     $t0,$t0,$carry          ; can not overflow
875         srdi    $carry,$t0,16
876         add     $t1,$t1,$carry
877         srdi    $carry,$t1,16
878         insrdi  $t0,$t1,16,32
879         add     $t2,$t2,$carry
880         ld      $t1,8($tp)              ; tp[j]
881         srdi    $carry,$t2,16
882         insrdi  $t0,$t2,16,16
883         add     $t3,$t3,$carry
884         ldu     $t2,16($tp)             ; tp[j+1]
885         srdi    $carry,$t3,16
886         insrdi  $t0,$t3,16,0            ; 0..63 bits
887         add     $t4,$t4,$carry
888         srdi    $carry,$t4,16
889         add     $t5,$t5,$carry
890         srdi    $carry,$t5,16
891         insrdi  $t4,$t5,16,32
892         add     $t6,$t6,$carry
893         srdi    $carry,$t6,16
894         insrdi  $t4,$t6,16,16
895         add     $t7,$t7,$carry
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)
900
901         addc    $t3,$t0,$t1
902 ___
903 $code.=<<___ if ($SIZE_T==4);           # adjust XER[CA]
904         extrdi  $t0,$t0,32,0
905         extrdi  $t1,$t1,32,0
906         adde    $t0,$t0,$t1
907 ___
908 $code.=<<___;
909         adde    $t5,$t4,$t2
910 ___
911 $code.=<<___ if ($SIZE_T==4);           # adjust XER[CA]
912         extrdi  $t4,$t4,32,0
913         extrdi  $t2,$t2,32,0
914         adde    $t4,$t4,$t2
915 ___
916 $code.=<<___;
917         addze   $carry,$carry
918
919         std     $t3,-16($tp)            ; tp[j-1]
920         std     $t5,-8($tp)             ; tp[j]
921
922         add     $carry,$carry,$ovf      ; comsume upmost overflow
923         add     $t6,$t6,$carry          ; can not overflow
924         srdi    $carry,$t6,16
925         add     $t7,$t7,$carry
926         insrdi  $t6,$t7,48,0
927         srdi    $ovf,$t7,48
928         std     $t6,0($tp)              ; tp[num-1]
929
930         slwi    $t7,$num,2
931         addi    $i,$i,8
932         subf    $nap_d,$t7,$nap_d       ; rewind pointer
933         cmpw    $i,$num
934         blt-    Louter
935 ___
936 \f
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`
943         addi    $t5,$np,8
944         addi    $t6,$rp,8
945         mtctr   $j
946
947 .align  4
948 Lsub:   ldx     $t0,$tp,$i
949         ldx     $t1,$np,$i
950         ldx     $t2,$t4,$i
951         ldx     $t3,$t5,$i
952         subfe   $t0,$t1,$t0     ; tp[j]-np[j]
953         subfe   $t2,$t3,$t2     ; tp[j+1]-np[j+1]
954         stdx    $t0,$rp,$i
955         stdx    $t2,$t6,$i
956         addi    $i,$i,16
957         bdnz-   Lsub
958
959         li      $i,0
960         subfe   $ovf,$i,$ovf    ; handle upmost overflow bit
961         and     $ap,$tp,$ovf
962         andc    $np,$rp,$ovf
963         or      $ap,$ap,$np     ; ap=borrow?tp:rp
964         addi    $t7,$ap,8
965         mtctr   $j
966
967 .align  4
968 Lcopy:                          ; copy or in-place refresh
969         ldx     $t0,$ap,$i
970         ldx     $t1,$t7,$i
971         std     $i,8($nap_d)    ; zap nap_d
972         std     $i,16($nap_d)
973         std     $i,24($nap_d)
974         std     $i,32($nap_d)
975         std     $i,40($nap_d)
976         std     $i,48($nap_d)
977         std     $i,56($nap_d)
978         stdu    $i,64($nap_d)
979         stdx    $t0,$rp,$i
980         stdx    $t1,$t6,$i
981         stdx    $i,$tp,$i       ; zap tp at once
982         stdx    $i,$t4,$i
983         addi    $i,$i,16
984         bdnz-   Lcopy
985 ___
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`
991         addi    $np,$np,-4
992         addi    $rp,$rp,-4
993         addi    $ap,$sp,`$FRAME+$TRANSFER+4`
994         mtctr   $j
995
996 .align  4
997 Lsub:   ld      $t0,8($tp)      ; load tp[j..j+3] in 64-bit word order
998         ldu     $t2,16($tp)
999         lwz     $t4,4($np)      ; load np[j..j+3] in 32-bit word order
1000         lwz     $t5,8($np)
1001         lwz     $t6,12($np)
1002         lwzu    $t7,16($np)
1003         extrdi  $t1,$t0,32,0
1004         extrdi  $t3,$t2,32,0
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]
1008          stw    $t1,8($ap)
1009         subfe   $t6,$t6,$t2     ; tp[j+2]-np[j+2]
1010          stw    $t2,12($ap)
1011         subfe   $t7,$t7,$t3     ; tp[j+3]-np[j+3]
1012          stwu   $t3,16($ap)
1013         stw     $t4,4($rp)
1014         stw     $t5,8($rp)
1015         stw     $t6,12($rp)
1016         stwu    $t7,16($rp)
1017         bdnz-   Lsub
1018
1019         li      $i,0
1020         subfe   $ovf,$i,$ovf    ; handle upmost overflow bit
1021         addi    $tp,$sp,`$FRAME+$TRANSFER+4`
1022         subf    $rp,$num,$rp    ; rewind rp
1023         and     $ap,$tp,$ovf
1024         andc    $np,$rp,$ovf
1025         or      $ap,$ap,$np     ; ap=borrow?tp:rp
1026         addi    $tp,$sp,`$FRAME+$TRANSFER`
1027         mtctr   $j
1028
1029 .align  4
1030 Lcopy:                          ; copy or in-place refresh
1031         lwz     $t0,4($ap)
1032         lwz     $t1,8($ap)
1033         lwz     $t2,12($ap)
1034         lwzu    $t3,16($ap)
1035         std     $i,8($nap_d)    ; zap nap_d
1036         std     $i,16($nap_d)
1037         std     $i,24($nap_d)
1038         std     $i,32($nap_d)
1039         std     $i,40($nap_d)
1040         std     $i,48($nap_d)
1041         std     $i,56($nap_d)
1042         stdu    $i,64($nap_d)
1043         stw     $t0,4($rp)
1044         stw     $t1,8($rp)
1045         stw     $t2,12($rp)
1046         stwu    $t3,16($rp)
1047         std     $i,8($tp)       ; zap tp at once
1048         stdu    $i,16($tp)
1049         bdnz-   Lcopy
1050 ___
1051 \f
1052 $code.=<<___;
1053         $POP    $i,0($sp)
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)
1065         lfd     f20,`-12*8`($i)
1066         lfd     f21,`-11*8`($i)
1067         lfd     f22,`-10*8`($i)
1068         lfd     f23,`-9*8`($i)
1069         lfd     f24,`-8*8`($i)
1070         lfd     f25,`-7*8`($i)
1071         lfd     f26,`-6*8`($i)
1072         lfd     f27,`-5*8`($i)
1073         lfd     f28,`-4*8`($i)
1074         lfd     f29,`-3*8`($i)
1075         lfd     f30,`-2*8`($i)
1076         lfd     f31,`-1*8`($i)
1077         mr      $sp,$i
1078         blr
1079         .long   0
1080         .byte   0,12,4,0,0x8c,10,6,0
1081         .long   0
1082 .size   .$fname,.-.$fname
1083
1084 .asciz  "Montgomery Multiplication for PPC64, CRYPTOGAMS by <appro\@openssl.org>"
1085 ___
1086
1087 $code =~ s/\`([^\`]*)\`/eval $1/gem;
1088 print $code;
1089 close STDOUT;