51a4b5fb36f99153603c045a91a82f2d46410b7f
[openssl.git] / crypto / bn / asm / mips.pl
1 #! /usr/bin/env perl
2 # Copyright 2010-2016 The OpenSSL Project Authors. All Rights Reserved.
3 #
4 # Licensed under the Apache License 2.0 (the "License").  You may not use
5 # this file except in compliance with the License.  You can obtain a copy
6 # in the file LICENSE in the source distribution or at
7 # https://www.openssl.org/source/license.html
8
9 #
10 # ====================================================================
11 # Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
12 # project.
13 #
14 # Rights for redistribution and usage in source and binary forms are
15 # granted according to the License. Warranty of any kind is disclaimed.
16 # ====================================================================
17
18
19 # July 1999
20 #
21 # This is drop-in MIPS III/IV ISA replacement for crypto/bn/bn_asm.c.
22 #
23 # The module is designed to work with either of the "new" MIPS ABI(5),
24 # namely N32 or N64, offered by IRIX 6.x. It's not meant to work under
25 # IRIX 5.x not only because it doesn't support new ABIs but also
26 # because 5.x kernels put R4x00 CPU into 32-bit mode and all those
27 # 64-bit instructions (daddu, dmultu, etc.) found below gonna only
28 # cause illegal instruction exception:-(
29 #
30 # In addition the code depends on preprocessor flags set up by MIPSpro
31 # compiler driver (either as or cc) and therefore (probably?) can't be
32 # compiled by the GNU assembler. GNU C driver manages fine though...
33 # I mean as long as -mmips-as is specified or is the default option,
34 # because then it simply invokes /usr/bin/as which in turn takes
35 # perfect care of the preprocessor definitions. Another neat feature
36 # offered by the MIPSpro assembler is an optimization pass. This gave
37 # me the opportunity to have the code looking more regular as all those
38 # architecture dependent instruction rescheduling details were left to
39 # the assembler. Cool, huh?
40 #
41 # Performance improvement is astonishing! 'apps/openssl speed rsa dsa'
42 # goes way over 3 times faster!
43 #
44 #                                       <appro@openssl.org>
45
46 # October 2010
47 #
48 # Adapt the module even for 32-bit ABIs and other OSes. The former was
49 # achieved by mechanical replacement of 64-bit arithmetic instructions
50 # such as dmultu, daddu, etc. with their 32-bit counterparts and
51 # adjusting offsets denoting multiples of BN_ULONG. Above mentioned
52 # >3x performance improvement naturally does not apply to 32-bit code
53 # [because there is no instruction 32-bit compiler can't use], one
54 # has to content with 40-85% improvement depending on benchmark and
55 # key length, more for longer keys.
56
57 $flavour = shift || "o32";
58 while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {}
59 open STDOUT,">$output";
60
61 if ($flavour =~ /64|n32/i) {
62         $LD="ld";
63         $ST="sd";
64         $MULTU="dmultu";
65         $DIVU="ddivu";
66         $ADDU="daddu";
67         $SUBU="dsubu";
68         $SRL="dsrl";
69         $SLL="dsll";
70         $BNSZ=8;
71         $PTR_ADD="daddu";
72         $PTR_SUB="dsubu";
73         $SZREG=8;
74         $REG_S="sd";
75         $REG_L="ld";
76 } else {
77         $LD="lw";
78         $ST="sw";
79         $MULTU="multu";
80         $DIVU="divu";
81         $ADDU="addu";
82         $SUBU="subu";
83         $SRL="srl";
84         $SLL="sll";
85         $BNSZ=4;
86         $PTR_ADD="addu";
87         $PTR_SUB="subu";
88         $SZREG=4;
89         $REG_S="sw";
90         $REG_L="lw";
91         $code=".set     mips2\n";
92 }
93
94 # Below is N32/64 register layout used in the original module.
95 #
96 ($zero,$at,$v0,$v1)=map("\$$_",(0..3));
97 ($a0,$a1,$a2,$a3,$a4,$a5,$a6,$a7)=map("\$$_",(4..11));
98 ($t0,$t1,$t2,$t3,$t8,$t9)=map("\$$_",(12..15,24,25));
99 ($s0,$s1,$s2,$s3,$s4,$s5,$s6,$s7)=map("\$$_",(16..23));
100 ($gp,$sp,$fp,$ra)=map("\$$_",(28..31));
101 ($ta0,$ta1,$ta2,$ta3)=($a4,$a5,$a6,$a7);
102 #
103 # No special adaptation is required for O32. NUBI on the other hand
104 # is treated by saving/restoring ($v1,$t0..$t3).
105
106 $gp=$v1 if ($flavour =~ /nubi/i);
107
108 $minus4=$v1;
109
110 $code.=<<___;
111 #include "mips_arch.h"
112
113 #if defined(_MIPS_ARCH_MIPS64R6)
114 # define ddivu(rs,rt)
115 # define mfqt(rd,rs,rt) ddivu   rd,rs,rt
116 # define mfrm(rd,rs,rt) dmodu   rd,rs,rt
117 #elif defined(_MIPS_ARCH_MIPS32R6)
118 # define divu(rs,rt)
119 # define mfqt(rd,rs,rt) divu    rd,rs,rt
120 # define mfrm(rd,rs,rt) modu    rd,rs,rt
121 #else
122 # define $DIVU(rs,rt)   $DIVU   $zero,rs,rt
123 # define mfqt(rd,rs,rt) mflo    rd
124 # define mfrm(rd,rs,rt) mfhi    rd
125 #endif
126
127 .rdata
128 .asciiz "mips3.s, Version 1.2"
129 .asciiz "MIPS II/III/IV ISA artwork by Andy Polyakov <appro\@fy.chalmers.se>"
130
131 .text
132 .set    noat
133
134 .align  5
135 .globl  bn_mul_add_words
136 .ent    bn_mul_add_words
137 bn_mul_add_words:
138         .set    noreorder
139         bgtz    $a2,bn_mul_add_words_internal
140         move    $v0,$zero
141         jr      $ra
142         move    $a0,$v0
143 .end    bn_mul_add_words
144
145 .align  5
146 .ent    bn_mul_add_words_internal
147 bn_mul_add_words_internal:
148 ___
149 $code.=<<___ if ($flavour =~ /nubi/i);
150         .frame  $sp,6*$SZREG,$ra
151         .mask   0x8000f008,-$SZREG
152         .set    noreorder
153         $PTR_SUB $sp,6*$SZREG
154         $REG_S  $ra,5*$SZREG($sp)
155         $REG_S  $t3,4*$SZREG($sp)
156         $REG_S  $t2,3*$SZREG($sp)
157         $REG_S  $t1,2*$SZREG($sp)
158         $REG_S  $t0,1*$SZREG($sp)
159         $REG_S  $gp,0*$SZREG($sp)
160 ___
161 $code.=<<___;
162         .set    reorder
163         li      $minus4,-4
164         and     $ta0,$a2,$minus4
165         beqz    $ta0,.L_bn_mul_add_words_tail
166
167 .L_bn_mul_add_words_loop:
168         $LD     $t0,0($a1)
169         $MULTU  ($t0,$a3)
170         $LD     $t1,0($a0)
171         $LD     $t2,$BNSZ($a1)
172         $LD     $t3,$BNSZ($a0)
173         $LD     $ta0,2*$BNSZ($a1)
174         $LD     $ta1,2*$BNSZ($a0)
175         $ADDU   $t1,$v0
176         sltu    $v0,$t1,$v0     # All manuals say it "compares 32-bit
177                                 # values", but it seems to work fine
178                                 # even on 64-bit registers.
179         mflo    ($at,$t0,$a3)
180         mfhi    ($t0,$t0,$a3)
181         $ADDU   $t1,$at
182         $ADDU   $v0,$t0
183          $MULTU ($t2,$a3)
184         sltu    $at,$t1,$at
185         $ST     $t1,0($a0)
186         $ADDU   $v0,$at
187
188         $LD     $ta2,3*$BNSZ($a1)
189         $LD     $ta3,3*$BNSZ($a0)
190         $ADDU   $t3,$v0
191         sltu    $v0,$t3,$v0
192         mflo    ($at,$t2,$a3)
193         mfhi    ($t2,$t2,$a3)
194         $ADDU   $t3,$at
195         $ADDU   $v0,$t2
196          $MULTU ($ta0,$a3)
197         sltu    $at,$t3,$at
198         $ST     $t3,$BNSZ($a0)
199         $ADDU   $v0,$at
200
201         subu    $a2,4
202         $PTR_ADD $a0,4*$BNSZ
203         $PTR_ADD $a1,4*$BNSZ
204         $ADDU   $ta1,$v0
205         sltu    $v0,$ta1,$v0
206         mflo    ($at,$ta0,$a3)
207         mfhi    ($ta0,$ta0,$a3)
208         $ADDU   $ta1,$at
209         $ADDU   $v0,$ta0
210          $MULTU ($ta2,$a3)
211         sltu    $at,$ta1,$at
212         $ST     $ta1,-2*$BNSZ($a0)
213         $ADDU   $v0,$at
214
215
216         and     $ta0,$a2,$minus4
217         $ADDU   $ta3,$v0
218         sltu    $v0,$ta3,$v0
219         mflo    ($at,$ta2,$a3)
220         mfhi    ($ta2,$ta2,$a3)
221         $ADDU   $ta3,$at
222         $ADDU   $v0,$ta2
223         sltu    $at,$ta3,$at
224         $ST     $ta3,-$BNSZ($a0)
225         .set    noreorder
226         bgtz    $ta0,.L_bn_mul_add_words_loop
227         $ADDU   $v0,$at
228
229         beqz    $a2,.L_bn_mul_add_words_return
230         nop
231
232 .L_bn_mul_add_words_tail:
233         .set    reorder
234         $LD     $t0,0($a1)
235         $MULTU  ($t0,$a3)
236         $LD     $t1,0($a0)
237         subu    $a2,1
238         $ADDU   $t1,$v0
239         sltu    $v0,$t1,$v0
240         mflo    ($at,$t0,$a3)
241         mfhi    ($t0,$t0,$a3)
242         $ADDU   $t1,$at
243         $ADDU   $v0,$t0
244         sltu    $at,$t1,$at
245         $ST     $t1,0($a0)
246         $ADDU   $v0,$at
247         beqz    $a2,.L_bn_mul_add_words_return
248
249         $LD     $t0,$BNSZ($a1)
250         $MULTU  ($t0,$a3)
251         $LD     $t1,$BNSZ($a0)
252         subu    $a2,1
253         $ADDU   $t1,$v0
254         sltu    $v0,$t1,$v0
255         mflo    ($at,$t0,$a3)
256         mfhi    ($t0,$t0,$a3)
257         $ADDU   $t1,$at
258         $ADDU   $v0,$t0
259         sltu    $at,$t1,$at
260         $ST     $t1,$BNSZ($a0)
261         $ADDU   $v0,$at
262         beqz    $a2,.L_bn_mul_add_words_return
263
264         $LD     $t0,2*$BNSZ($a1)
265         $MULTU  ($t0,$a3)
266         $LD     $t1,2*$BNSZ($a0)
267         $ADDU   $t1,$v0
268         sltu    $v0,$t1,$v0
269         mflo    ($at,$t0,$a3)
270         mfhi    ($t0,$t0,$a3)
271         $ADDU   $t1,$at
272         $ADDU   $v0,$t0
273         sltu    $at,$t1,$at
274         $ST     $t1,2*$BNSZ($a0)
275         $ADDU   $v0,$at
276
277 .L_bn_mul_add_words_return:
278         .set    noreorder
279 ___
280 $code.=<<___ if ($flavour =~ /nubi/i);
281         $REG_L  $t3,4*$SZREG($sp)
282         $REG_L  $t2,3*$SZREG($sp)
283         $REG_L  $t1,2*$SZREG($sp)
284         $REG_L  $t0,1*$SZREG($sp)
285         $REG_L  $gp,0*$SZREG($sp)
286         $PTR_ADD $sp,6*$SZREG
287 ___
288 $code.=<<___;
289         jr      $ra
290         move    $a0,$v0
291 .end    bn_mul_add_words_internal
292
293 .align  5
294 .globl  bn_mul_words
295 .ent    bn_mul_words
296 bn_mul_words:
297         .set    noreorder
298         bgtz    $a2,bn_mul_words_internal
299         move    $v0,$zero
300         jr      $ra
301         move    $a0,$v0
302 .end    bn_mul_words
303
304 .align  5
305 .ent    bn_mul_words_internal
306 bn_mul_words_internal:
307 ___
308 $code.=<<___ if ($flavour =~ /nubi/i);
309         .frame  $sp,6*$SZREG,$ra
310         .mask   0x8000f008,-$SZREG
311         .set    noreorder
312         $PTR_SUB $sp,6*$SZREG
313         $REG_S  $ra,5*$SZREG($sp)
314         $REG_S  $t3,4*$SZREG($sp)
315         $REG_S  $t2,3*$SZREG($sp)
316         $REG_S  $t1,2*$SZREG($sp)
317         $REG_S  $t0,1*$SZREG($sp)
318         $REG_S  $gp,0*$SZREG($sp)
319 ___
320 $code.=<<___;
321         .set    reorder
322         li      $minus4,-4
323         and     $ta0,$a2,$minus4
324         beqz    $ta0,.L_bn_mul_words_tail
325
326 .L_bn_mul_words_loop:
327         $LD     $t0,0($a1)
328         $MULTU  ($t0,$a3)
329         $LD     $t2,$BNSZ($a1)
330         $LD     $ta0,2*$BNSZ($a1)
331         $LD     $ta2,3*$BNSZ($a1)
332         mflo    ($at,$t0,$a3)
333         mfhi    ($t0,$t0,$a3)
334         $ADDU   $v0,$at
335         sltu    $t1,$v0,$at
336          $MULTU ($t2,$a3)
337         $ST     $v0,0($a0)
338         $ADDU   $v0,$t1,$t0
339
340         subu    $a2,4
341         $PTR_ADD $a0,4*$BNSZ
342         $PTR_ADD $a1,4*$BNSZ
343         mflo    ($at,$t2,$a3)
344         mfhi    ($t2,$t2,$a3)
345         $ADDU   $v0,$at
346         sltu    $t3,$v0,$at
347          $MULTU ($ta0,$a3)
348         $ST     $v0,-3*$BNSZ($a0)
349         $ADDU   $v0,$t3,$t2
350
351         mflo    ($at,$ta0,$a3)
352         mfhi    ($ta0,$ta0,$a3)
353         $ADDU   $v0,$at
354         sltu    $ta1,$v0,$at
355          $MULTU ($ta2,$a3)
356         $ST     $v0,-2*$BNSZ($a0)
357         $ADDU   $v0,$ta1,$ta0
358
359         and     $ta0,$a2,$minus4
360         mflo    ($at,$ta2,$a3)
361         mfhi    ($ta2,$ta2,$a3)
362         $ADDU   $v0,$at
363         sltu    $ta3,$v0,$at
364         $ST     $v0,-$BNSZ($a0)
365         .set    noreorder
366         bgtz    $ta0,.L_bn_mul_words_loop
367         $ADDU   $v0,$ta3,$ta2
368
369         beqz    $a2,.L_bn_mul_words_return
370         nop
371
372 .L_bn_mul_words_tail:
373         .set    reorder
374         $LD     $t0,0($a1)
375         $MULTU  ($t0,$a3)
376         subu    $a2,1
377         mflo    ($at,$t0,$a3)
378         mfhi    ($t0,$t0,$a3)
379         $ADDU   $v0,$at
380         sltu    $t1,$v0,$at
381         $ST     $v0,0($a0)
382         $ADDU   $v0,$t1,$t0
383         beqz    $a2,.L_bn_mul_words_return
384
385         $LD     $t0,$BNSZ($a1)
386         $MULTU  ($t0,$a3)
387         subu    $a2,1
388         mflo    ($at,$t0,$a3)
389         mfhi    ($t0,$t0,$a3)
390         $ADDU   $v0,$at
391         sltu    $t1,$v0,$at
392         $ST     $v0,$BNSZ($a0)
393         $ADDU   $v0,$t1,$t0
394         beqz    $a2,.L_bn_mul_words_return
395
396         $LD     $t0,2*$BNSZ($a1)
397         $MULTU  ($t0,$a3)
398         mflo    ($at,$t0,$a3)
399         mfhi    ($t0,$t0,$a3)
400         $ADDU   $v0,$at
401         sltu    $t1,$v0,$at
402         $ST     $v0,2*$BNSZ($a0)
403         $ADDU   $v0,$t1,$t0
404
405 .L_bn_mul_words_return:
406         .set    noreorder
407 ___
408 $code.=<<___ if ($flavour =~ /nubi/i);
409         $REG_L  $t3,4*$SZREG($sp)
410         $REG_L  $t2,3*$SZREG($sp)
411         $REG_L  $t1,2*$SZREG($sp)
412         $REG_L  $t0,1*$SZREG($sp)
413         $REG_L  $gp,0*$SZREG($sp)
414         $PTR_ADD $sp,6*$SZREG
415 ___
416 $code.=<<___;
417         jr      $ra
418         move    $a0,$v0
419 .end    bn_mul_words_internal
420
421 .align  5
422 .globl  bn_sqr_words
423 .ent    bn_sqr_words
424 bn_sqr_words:
425         .set    noreorder
426         bgtz    $a2,bn_sqr_words_internal
427         move    $v0,$zero
428         jr      $ra
429         move    $a0,$v0
430 .end    bn_sqr_words
431
432 .align  5
433 .ent    bn_sqr_words_internal
434 bn_sqr_words_internal:
435 ___
436 $code.=<<___ if ($flavour =~ /nubi/i);
437         .frame  $sp,6*$SZREG,$ra
438         .mask   0x8000f008,-$SZREG
439         .set    noreorder
440         $PTR_SUB $sp,6*$SZREG
441         $REG_S  $ra,5*$SZREG($sp)
442         $REG_S  $t3,4*$SZREG($sp)
443         $REG_S  $t2,3*$SZREG($sp)
444         $REG_S  $t1,2*$SZREG($sp)
445         $REG_S  $t0,1*$SZREG($sp)
446         $REG_S  $gp,0*$SZREG($sp)
447 ___
448 $code.=<<___;
449         .set    reorder
450         li      $minus4,-4
451         and     $ta0,$a2,$minus4
452         beqz    $ta0,.L_bn_sqr_words_tail
453
454 .L_bn_sqr_words_loop:
455         $LD     $t0,0($a1)
456         $MULTU  ($t0,$t0)
457         $LD     $t2,$BNSZ($a1)
458         $LD     $ta0,2*$BNSZ($a1)
459         $LD     $ta2,3*$BNSZ($a1)
460         mflo    ($t1,$t0,$t0)
461         mfhi    ($t0,$t0,$t0)
462         $ST     $t1,0($a0)
463         $ST     $t0,$BNSZ($a0)
464
465         $MULTU  ($t2,$t2)
466         subu    $a2,4
467         $PTR_ADD $a0,8*$BNSZ
468         $PTR_ADD $a1,4*$BNSZ
469         mflo    ($t3,$t2,$t2)
470         mfhi    ($t2,$t2,$t2)
471         $ST     $t3,-6*$BNSZ($a0)
472         $ST     $t2,-5*$BNSZ($a0)
473
474         $MULTU  ($ta0,$ta0)
475         mflo    ($ta1,$ta0,$ta0)
476         mfhi    ($ta0,$ta0,$ta0)
477         $ST     $ta1,-4*$BNSZ($a0)
478         $ST     $ta0,-3*$BNSZ($a0)
479
480
481         $MULTU  ($ta2,$ta2)
482         and     $ta0,$a2,$minus4
483         mflo    ($ta3,$ta2,$ta2)
484         mfhi    ($ta2,$ta2,$ta2)
485         $ST     $ta3,-2*$BNSZ($a0)
486
487         .set    noreorder
488         bgtz    $ta0,.L_bn_sqr_words_loop
489         $ST     $ta2,-$BNSZ($a0)
490
491         beqz    $a2,.L_bn_sqr_words_return
492         nop
493
494 .L_bn_sqr_words_tail:
495         .set    reorder
496         $LD     $t0,0($a1)
497         $MULTU  ($t0,$t0)
498         subu    $a2,1
499         mflo    ($t1,$t0,$t0)
500         mfhi    ($t0,$t0,$t0)
501         $ST     $t1,0($a0)
502         $ST     $t0,$BNSZ($a0)
503         beqz    $a2,.L_bn_sqr_words_return
504
505         $LD     $t0,$BNSZ($a1)
506         $MULTU  ($t0,$t0)
507         subu    $a2,1
508         mflo    ($t1,$t0,$t0)
509         mfhi    ($t0,$t0,$t0)
510         $ST     $t1,2*$BNSZ($a0)
511         $ST     $t0,3*$BNSZ($a0)
512         beqz    $a2,.L_bn_sqr_words_return
513
514         $LD     $t0,2*$BNSZ($a1)
515         $MULTU  ($t0,$t0)
516         mflo    ($t1,$t0,$t0)
517         mfhi    ($t0,$t0,$t0)
518         $ST     $t1,4*$BNSZ($a0)
519         $ST     $t0,5*$BNSZ($a0)
520
521 .L_bn_sqr_words_return:
522         .set    noreorder
523 ___
524 $code.=<<___ if ($flavour =~ /nubi/i);
525         $REG_L  $t3,4*$SZREG($sp)
526         $REG_L  $t2,3*$SZREG($sp)
527         $REG_L  $t1,2*$SZREG($sp)
528         $REG_L  $t0,1*$SZREG($sp)
529         $REG_L  $gp,0*$SZREG($sp)
530         $PTR_ADD $sp,6*$SZREG
531 ___
532 $code.=<<___;
533         jr      $ra
534         move    $a0,$v0
535
536 .end    bn_sqr_words_internal
537
538 .align  5
539 .globl  bn_add_words
540 .ent    bn_add_words
541 bn_add_words:
542         .set    noreorder
543         bgtz    $a3,bn_add_words_internal
544         move    $v0,$zero
545         jr      $ra
546         move    $a0,$v0
547 .end    bn_add_words
548
549 .align  5
550 .ent    bn_add_words_internal
551 bn_add_words_internal:
552 ___
553 $code.=<<___ if ($flavour =~ /nubi/i);
554         .frame  $sp,6*$SZREG,$ra
555         .mask   0x8000f008,-$SZREG
556         .set    noreorder
557         $PTR_SUB $sp,6*$SZREG
558         $REG_S  $ra,5*$SZREG($sp)
559         $REG_S  $t3,4*$SZREG($sp)
560         $REG_S  $t2,3*$SZREG($sp)
561         $REG_S  $t1,2*$SZREG($sp)
562         $REG_S  $t0,1*$SZREG($sp)
563         $REG_S  $gp,0*$SZREG($sp)
564 ___
565 $code.=<<___;
566         .set    reorder
567         li      $minus4,-4
568         and     $at,$a3,$minus4
569         beqz    $at,.L_bn_add_words_tail
570
571 .L_bn_add_words_loop:
572         $LD     $t0,0($a1)
573         $LD     $ta0,0($a2)
574         subu    $a3,4
575         $LD     $t1,$BNSZ($a1)
576         and     $at,$a3,$minus4
577         $LD     $t2,2*$BNSZ($a1)
578         $PTR_ADD $a2,4*$BNSZ
579         $LD     $t3,3*$BNSZ($a1)
580         $PTR_ADD $a0,4*$BNSZ
581         $LD     $ta1,-3*$BNSZ($a2)
582         $PTR_ADD $a1,4*$BNSZ
583         $LD     $ta2,-2*$BNSZ($a2)
584         $LD     $ta3,-$BNSZ($a2)
585         $ADDU   $ta0,$t0
586         sltu    $t8,$ta0,$t0
587         $ADDU   $t0,$ta0,$v0
588         sltu    $v0,$t0,$ta0
589         $ST     $t0,-4*$BNSZ($a0)
590         $ADDU   $v0,$t8
591
592         $ADDU   $ta1,$t1
593         sltu    $t9,$ta1,$t1
594         $ADDU   $t1,$ta1,$v0
595         sltu    $v0,$t1,$ta1
596         $ST     $t1,-3*$BNSZ($a0)
597         $ADDU   $v0,$t9
598
599         $ADDU   $ta2,$t2
600         sltu    $t8,$ta2,$t2
601         $ADDU   $t2,$ta2,$v0
602         sltu    $v0,$t2,$ta2
603         $ST     $t2,-2*$BNSZ($a0)
604         $ADDU   $v0,$t8
605
606         $ADDU   $ta3,$t3
607         sltu    $t9,$ta3,$t3
608         $ADDU   $t3,$ta3,$v0
609         sltu    $v0,$t3,$ta3
610         $ST     $t3,-$BNSZ($a0)
611
612         .set    noreorder
613         bgtz    $at,.L_bn_add_words_loop
614         $ADDU   $v0,$t9
615
616         beqz    $a3,.L_bn_add_words_return
617         nop
618
619 .L_bn_add_words_tail:
620         .set    reorder
621         $LD     $t0,0($a1)
622         $LD     $ta0,0($a2)
623         $ADDU   $ta0,$t0
624         subu    $a3,1
625         sltu    $t8,$ta0,$t0
626         $ADDU   $t0,$ta0,$v0
627         sltu    $v0,$t0,$ta0
628         $ST     $t0,0($a0)
629         $ADDU   $v0,$t8
630         beqz    $a3,.L_bn_add_words_return
631
632         $LD     $t1,$BNSZ($a1)
633         $LD     $ta1,$BNSZ($a2)
634         $ADDU   $ta1,$t1
635         subu    $a3,1
636         sltu    $t9,$ta1,$t1
637         $ADDU   $t1,$ta1,$v0
638         sltu    $v0,$t1,$ta1
639         $ST     $t1,$BNSZ($a0)
640         $ADDU   $v0,$t9
641         beqz    $a3,.L_bn_add_words_return
642
643         $LD     $t2,2*$BNSZ($a1)
644         $LD     $ta2,2*$BNSZ($a2)
645         $ADDU   $ta2,$t2
646         sltu    $t8,$ta2,$t2
647         $ADDU   $t2,$ta2,$v0
648         sltu    $v0,$t2,$ta2
649         $ST     $t2,2*$BNSZ($a0)
650         $ADDU   $v0,$t8
651
652 .L_bn_add_words_return:
653         .set    noreorder
654 ___
655 $code.=<<___ if ($flavour =~ /nubi/i);
656         $REG_L  $t3,4*$SZREG($sp)
657         $REG_L  $t2,3*$SZREG($sp)
658         $REG_L  $t1,2*$SZREG($sp)
659         $REG_L  $t0,1*$SZREG($sp)
660         $REG_L  $gp,0*$SZREG($sp)
661         $PTR_ADD $sp,6*$SZREG
662 ___
663 $code.=<<___;
664         jr      $ra
665         move    $a0,$v0
666
667 .end    bn_add_words_internal
668
669 .align  5
670 .globl  bn_sub_words
671 .ent    bn_sub_words
672 bn_sub_words:
673         .set    noreorder
674         bgtz    $a3,bn_sub_words_internal
675         move    $v0,$zero
676         jr      $ra
677         move    $a0,$zero
678 .end    bn_sub_words
679
680 .align  5
681 .ent    bn_sub_words_internal
682 bn_sub_words_internal:
683 ___
684 $code.=<<___ if ($flavour =~ /nubi/i);
685         .frame  $sp,6*$SZREG,$ra
686         .mask   0x8000f008,-$SZREG
687         .set    noreorder
688         $PTR_SUB $sp,6*$SZREG
689         $REG_S  $ra,5*$SZREG($sp)
690         $REG_S  $t3,4*$SZREG($sp)
691         $REG_S  $t2,3*$SZREG($sp)
692         $REG_S  $t1,2*$SZREG($sp)
693         $REG_S  $t0,1*$SZREG($sp)
694         $REG_S  $gp,0*$SZREG($sp)
695 ___
696 $code.=<<___;
697         .set    reorder
698         li      $minus4,-4
699         and     $at,$a3,$minus4
700         beqz    $at,.L_bn_sub_words_tail
701
702 .L_bn_sub_words_loop:
703         $LD     $t0,0($a1)
704         $LD     $ta0,0($a2)
705         subu    $a3,4
706         $LD     $t1,$BNSZ($a1)
707         and     $at,$a3,$minus4
708         $LD     $t2,2*$BNSZ($a1)
709         $PTR_ADD $a2,4*$BNSZ
710         $LD     $t3,3*$BNSZ($a1)
711         $PTR_ADD $a0,4*$BNSZ
712         $LD     $ta1,-3*$BNSZ($a2)
713         $PTR_ADD $a1,4*$BNSZ
714         $LD     $ta2,-2*$BNSZ($a2)
715         $LD     $ta3,-$BNSZ($a2)
716         sltu    $t8,$t0,$ta0
717         $SUBU   $ta0,$t0,$ta0
718         $SUBU   $t0,$ta0,$v0
719         sgtu    $v0,$t0,$ta0
720         $ST     $t0,-4*$BNSZ($a0)
721         $ADDU   $v0,$t8
722
723         sltu    $t9,$t1,$ta1
724         $SUBU   $ta1,$t1,$ta1
725         $SUBU   $t1,$ta1,$v0
726         sgtu    $v0,$t1,$ta1
727         $ST     $t1,-3*$BNSZ($a0)
728         $ADDU   $v0,$t9
729
730
731         sltu    $t8,$t2,$ta2
732         $SUBU   $ta2,$t2,$ta2
733         $SUBU   $t2,$ta2,$v0
734         sgtu    $v0,$t2,$ta2
735         $ST     $t2,-2*$BNSZ($a0)
736         $ADDU   $v0,$t8
737
738         sltu    $t9,$t3,$ta3
739         $SUBU   $ta3,$t3,$ta3
740         $SUBU   $t3,$ta3,$v0
741         sgtu    $v0,$t3,$ta3
742         $ST     $t3,-$BNSZ($a0)
743
744         .set    noreorder
745         bgtz    $at,.L_bn_sub_words_loop
746         $ADDU   $v0,$t9
747
748         beqz    $a3,.L_bn_sub_words_return
749         nop
750
751 .L_bn_sub_words_tail:
752         .set    reorder
753         $LD     $t0,0($a1)
754         $LD     $ta0,0($a2)
755         subu    $a3,1
756         sltu    $t8,$t0,$ta0
757         $SUBU   $ta0,$t0,$ta0
758         $SUBU   $t0,$ta0,$v0
759         sgtu    $v0,$t0,$ta0
760         $ST     $t0,0($a0)
761         $ADDU   $v0,$t8
762         beqz    $a3,.L_bn_sub_words_return
763
764         $LD     $t1,$BNSZ($a1)
765         subu    $a3,1
766         $LD     $ta1,$BNSZ($a2)
767         sltu    $t9,$t1,$ta1
768         $SUBU   $ta1,$t1,$ta1
769         $SUBU   $t1,$ta1,$v0
770         sgtu    $v0,$t1,$ta1
771         $ST     $t1,$BNSZ($a0)
772         $ADDU   $v0,$t9
773         beqz    $a3,.L_bn_sub_words_return
774
775         $LD     $t2,2*$BNSZ($a1)
776         $LD     $ta2,2*$BNSZ($a2)
777         sltu    $t8,$t2,$ta2
778         $SUBU   $ta2,$t2,$ta2
779         $SUBU   $t2,$ta2,$v0
780         sgtu    $v0,$t2,$ta2
781         $ST     $t2,2*$BNSZ($a0)
782         $ADDU   $v0,$t8
783
784 .L_bn_sub_words_return:
785         .set    noreorder
786 ___
787 $code.=<<___ if ($flavour =~ /nubi/i);
788         $REG_L  $t3,4*$SZREG($sp)
789         $REG_L  $t2,3*$SZREG($sp)
790         $REG_L  $t1,2*$SZREG($sp)
791         $REG_L  $t0,1*$SZREG($sp)
792         $REG_L  $gp,0*$SZREG($sp)
793         $PTR_ADD $sp,6*$SZREG
794 ___
795 $code.=<<___;
796         jr      $ra
797         move    $a0,$v0
798 .end    bn_sub_words_internal
799
800 #if 0
801 /*
802  * The bn_div_3_words entry point is re-used for constant-time interface.
803  * Implementation is retained as hystorical reference.
804  */
805 .align 5
806 .globl  bn_div_3_words
807 .ent    bn_div_3_words
808 bn_div_3_words:
809         .set    noreorder
810         move    $a3,$a0         # we know that bn_div_words does not
811                                 # touch $a3, $ta2, $ta3 and preserves $a2
812                                 # so that we can save two arguments
813                                 # and return address in registers
814                                 # instead of stack:-)
815
816         $LD     $a0,($a3)
817         move    $ta2,$a1
818         bne     $a0,$a2,bn_div_3_words_internal
819         $LD     $a1,-$BNSZ($a3)
820         li      $v0,-1
821         jr      $ra
822         move    $a0,$v0
823 .end    bn_div_3_words
824
825 .align  5
826 .ent    bn_div_3_words_internal
827 bn_div_3_words_internal:
828 ___
829 $code.=<<___ if ($flavour =~ /nubi/i);
830         .frame  $sp,6*$SZREG,$ra
831         .mask   0x8000f008,-$SZREG
832         .set    noreorder
833         $PTR_SUB $sp,6*$SZREG
834         $REG_S  $ra,5*$SZREG($sp)
835         $REG_S  $t3,4*$SZREG($sp)
836         $REG_S  $t2,3*$SZREG($sp)
837         $REG_S  $t1,2*$SZREG($sp)
838         $REG_S  $t0,1*$SZREG($sp)
839         $REG_S  $gp,0*$SZREG($sp)
840 ___
841 $code.=<<___;
842         .set    reorder
843         move    $ta3,$ra
844         bal     bn_div_words_internal
845         move    $ra,$ta3
846         $MULTU  ($ta2,$v0)
847         $LD     $t2,-2*$BNSZ($a3)
848         move    $ta0,$zero
849         mfhi    ($t1,$ta2,$v0)
850         mflo    ($t0,$ta2,$v0)
851         sltu    $t8,$t1,$a1
852 .L_bn_div_3_words_inner_loop:
853         bnez    $t8,.L_bn_div_3_words_inner_loop_done
854         sgeu    $at,$t2,$t0
855         seq     $t9,$t1,$a1
856         and     $at,$t9
857         sltu    $t3,$t0,$ta2
858         $ADDU   $a1,$a2
859         $SUBU   $t1,$t3
860         $SUBU   $t0,$ta2
861         sltu    $t8,$t1,$a1
862         sltu    $ta0,$a1,$a2
863         or      $t8,$ta0
864         .set    noreorder
865         beqz    $at,.L_bn_div_3_words_inner_loop
866         $SUBU   $v0,1
867         $ADDU   $v0,1
868         .set    reorder
869 .L_bn_div_3_words_inner_loop_done:
870         .set    noreorder
871 ___
872 $code.=<<___ if ($flavour =~ /nubi/i);
873         $REG_L  $t3,4*$SZREG($sp)
874         $REG_L  $t2,3*$SZREG($sp)
875         $REG_L  $t1,2*$SZREG($sp)
876         $REG_L  $t0,1*$SZREG($sp)
877         $REG_L  $gp,0*$SZREG($sp)
878         $PTR_ADD $sp,6*$SZREG
879 ___
880 $code.=<<___;
881         jr      $ra
882         move    $a0,$v0
883 .end    bn_div_3_words_internal
884 #endif
885
886 .align  5
887 .globl  bn_div_words
888 .ent    bn_div_words
889 bn_div_words:
890         .set    noreorder
891         bnez    $a2,bn_div_words_internal
892         li      $v0,-1          # I would rather signal div-by-zero
893                                 # which can be done with 'break 7'
894         jr      $ra
895         move    $a0,$v0
896 .end    bn_div_words
897
898 .align  5
899 .ent    bn_div_words_internal
900 bn_div_words_internal:
901 ___
902 $code.=<<___ if ($flavour =~ /nubi/i);
903         .frame  $sp,6*$SZREG,$ra
904         .mask   0x8000f008,-$SZREG
905         .set    noreorder
906         $PTR_SUB $sp,6*$SZREG
907         $REG_S  $ra,5*$SZREG($sp)
908         $REG_S  $t3,4*$SZREG($sp)
909         $REG_S  $t2,3*$SZREG($sp)
910         $REG_S  $t1,2*$SZREG($sp)
911         $REG_S  $t0,1*$SZREG($sp)
912         $REG_S  $gp,0*$SZREG($sp)
913 ___
914 $code.=<<___;
915         move    $v1,$zero
916         bltz    $a2,.L_bn_div_words_body
917         move    $t9,$v1
918         $SLL    $a2,1
919         bgtz    $a2,.-4
920         addu    $t9,1
921
922         .set    reorder
923         negu    $t1,$t9
924         li      $t2,-1
925         $SLL    $t2,$t1
926         and     $t2,$a0
927         $SRL    $at,$a1,$t1
928         .set    noreorder
929         beqz    $t2,.+12
930         nop
931         break   6               # signal overflow
932         .set    reorder
933         $SLL    $a0,$t9
934         $SLL    $a1,$t9
935         or      $a0,$at
936 ___
937 $QT=$ta0;
938 $HH=$ta1;
939 $DH=$v1;
940 $code.=<<___;
941 .L_bn_div_words_body:
942         $SRL    $DH,$a2,4*$BNSZ # bits
943         sgeu    $at,$a0,$a2
944         .set    noreorder
945         beqz    $at,.+12
946         nop
947         $SUBU   $a0,$a2
948         .set    reorder
949
950         li      $QT,-1
951         $SRL    $HH,$a0,4*$BNSZ # bits
952         $SRL    $QT,4*$BNSZ     # q=0xffffffff
953         beq     $DH,$HH,.L_bn_div_words_skip_div1
954         $DIVU   ($a0,$DH)
955         mfqt    ($QT,$a0,$DH)
956 .L_bn_div_words_skip_div1:
957         $MULTU  ($a2,$QT)
958         $SLL    $t3,$a0,4*$BNSZ # bits
959         $SRL    $at,$a1,4*$BNSZ # bits
960         or      $t3,$at
961         mflo    ($t0,$a2,$QT)
962         mfhi    ($t1,$a2,$QT)
963 .L_bn_div_words_inner_loop1:
964         sltu    $t2,$t3,$t0
965         seq     $t8,$HH,$t1
966         sltu    $at,$HH,$t1
967         and     $t2,$t8
968         sltu    $v0,$t0,$a2
969         or      $at,$t2
970         .set    noreorder
971         beqz    $at,.L_bn_div_words_inner_loop1_done
972         $SUBU   $t1,$v0
973         $SUBU   $t0,$a2
974         b       .L_bn_div_words_inner_loop1
975         $SUBU   $QT,1
976         .set    reorder
977 .L_bn_div_words_inner_loop1_done:
978
979         $SLL    $a1,4*$BNSZ     # bits
980         $SUBU   $a0,$t3,$t0
981         $SLL    $v0,$QT,4*$BNSZ # bits
982
983         li      $QT,-1
984         $SRL    $HH,$a0,4*$BNSZ # bits
985         $SRL    $QT,4*$BNSZ     # q=0xffffffff
986         beq     $DH,$HH,.L_bn_div_words_skip_div2
987         $DIVU   ($a0,$DH)
988         mfqt    ($QT,$a0,$DH)
989 .L_bn_div_words_skip_div2:
990         $MULTU  ($a2,$QT)
991         $SLL    $t3,$a0,4*$BNSZ # bits
992         $SRL    $at,$a1,4*$BNSZ # bits
993         or      $t3,$at
994         mflo    ($t0,$a2,$QT)
995         mfhi    ($t1,$a2,$QT)
996 .L_bn_div_words_inner_loop2:
997         sltu    $t2,$t3,$t0
998         seq     $t8,$HH,$t1
999         sltu    $at,$HH,$t1
1000         and     $t2,$t8
1001         sltu    $v1,$t0,$a2
1002         or      $at,$t2
1003         .set    noreorder
1004         beqz    $at,.L_bn_div_words_inner_loop2_done
1005         $SUBU   $t1,$v1
1006         $SUBU   $t0,$a2
1007         b       .L_bn_div_words_inner_loop2
1008         $SUBU   $QT,1
1009         .set    reorder
1010 .L_bn_div_words_inner_loop2_done:
1011
1012         $SUBU   $a0,$t3,$t0
1013         or      $v0,$QT
1014         $SRL    $v1,$a0,$t9     # $v1 contains remainder if anybody wants it
1015         $SRL    $a2,$t9         # restore $a2
1016
1017         .set    noreorder
1018         move    $a1,$v1
1019 ___
1020 $code.=<<___ if ($flavour =~ /nubi/i);
1021         $REG_L  $t3,4*$SZREG($sp)
1022         $REG_L  $t2,3*$SZREG($sp)
1023         $REG_L  $t1,2*$SZREG($sp)
1024         $REG_L  $t0,1*$SZREG($sp)
1025         $REG_L  $gp,0*$SZREG($sp)
1026         $PTR_ADD $sp,6*$SZREG
1027 ___
1028 $code.=<<___;
1029         jr      $ra
1030         move    $a0,$v0
1031 .end    bn_div_words_internal
1032 ___
1033 undef $HH; undef $QT; undef $DH;
1034
1035 ($a_0,$a_1,$a_2,$a_3)=($t0,$t1,$t2,$t3);
1036 ($b_0,$b_1,$b_2,$b_3)=($ta0,$ta1,$ta2,$ta3);
1037
1038 ($a_4,$a_5,$a_6,$a_7)=($s0,$s2,$s4,$a1); # once we load a[7], no use for $a1
1039 ($b_4,$b_5,$b_6,$b_7)=($s1,$s3,$s5,$a2); # once we load b[7], no use for $a2
1040
1041 ($t_1,$t_2,$c_1,$c_2,$c_3)=($t8,$t9,$v0,$v1,$a3);
1042
1043 $code.=<<___;
1044
1045 .align  5
1046 .globl  bn_mul_comba8
1047 .ent    bn_mul_comba8
1048 bn_mul_comba8:
1049         .set    noreorder
1050 ___
1051 $code.=<<___ if ($flavour =~ /nubi/i);
1052         .frame  $sp,12*$SZREG,$ra
1053         .mask   0x803ff008,-$SZREG
1054         $PTR_SUB $sp,12*$SZREG
1055         $REG_S  $ra,11*$SZREG($sp)
1056         $REG_S  $s5,10*$SZREG($sp)
1057         $REG_S  $s4,9*$SZREG($sp)
1058         $REG_S  $s3,8*$SZREG($sp)
1059         $REG_S  $s2,7*$SZREG($sp)
1060         $REG_S  $s1,6*$SZREG($sp)
1061         $REG_S  $s0,5*$SZREG($sp)
1062         $REG_S  $t3,4*$SZREG($sp)
1063         $REG_S  $t2,3*$SZREG($sp)
1064         $REG_S  $t1,2*$SZREG($sp)
1065         $REG_S  $t0,1*$SZREG($sp)
1066         $REG_S  $gp,0*$SZREG($sp)
1067 ___
1068 $code.=<<___ if ($flavour !~ /nubi/i);
1069         .frame  $sp,6*$SZREG,$ra
1070         .mask   0x003f0000,-$SZREG
1071         $PTR_SUB $sp,6*$SZREG
1072         $REG_S  $s5,5*$SZREG($sp)
1073         $REG_S  $s4,4*$SZREG($sp)
1074         $REG_S  $s3,3*$SZREG($sp)
1075         $REG_S  $s2,2*$SZREG($sp)
1076         $REG_S  $s1,1*$SZREG($sp)
1077         $REG_S  $s0,0*$SZREG($sp)
1078 ___
1079 $code.=<<___;
1080
1081         .set    reorder
1082         $LD     $a_0,0($a1)     # If compiled with -mips3 option on
1083                                 # R5000 box assembler barks on this
1084                                 # 1ine with "should not have mult/div
1085                                 # as last instruction in bb (R10K
1086                                 # bug)" warning. If anybody out there
1087                                 # has a clue about how to circumvent
1088                                 # this do send me a note.
1089                                 #               <appro\@fy.chalmers.se>
1090
1091         $LD     $b_0,0($a2)
1092         $LD     $a_1,$BNSZ($a1)
1093         $LD     $a_2,2*$BNSZ($a1)
1094         $MULTU  ($a_0,$b_0)             # mul_add_c(a[0],b[0],c1,c2,c3);
1095         $LD     $a_3,3*$BNSZ($a1)
1096         $LD     $b_1,$BNSZ($a2)
1097         $LD     $b_2,2*$BNSZ($a2)
1098         $LD     $b_3,3*$BNSZ($a2)
1099         mflo    ($c_1,$a_0,$b_0)
1100         mfhi    ($c_2,$a_0,$b_0)
1101
1102         $LD     $a_4,4*$BNSZ($a1)
1103         $LD     $a_5,5*$BNSZ($a1)
1104         $MULTU  ($a_0,$b_1)             # mul_add_c(a[0],b[1],c2,c3,c1);
1105         $LD     $a_6,6*$BNSZ($a1)
1106         $LD     $a_7,7*$BNSZ($a1)
1107         $LD     $b_4,4*$BNSZ($a2)
1108         $LD     $b_5,5*$BNSZ($a2)
1109         mflo    ($t_1,$a_0,$b_1)
1110         mfhi    ($t_2,$a_0,$b_1)
1111         $ADDU   $c_2,$t_1
1112         sltu    $at,$c_2,$t_1
1113         $MULTU  ($a_1,$b_0)             # mul_add_c(a[1],b[0],c2,c3,c1);
1114         $ADDU   $c_3,$t_2,$at
1115         $LD     $b_6,6*$BNSZ($a2)
1116         $LD     $b_7,7*$BNSZ($a2)
1117         $ST     $c_1,0($a0)     # r[0]=c1;
1118         mflo    ($t_1,$a_1,$b_0)
1119         mfhi    ($t_2,$a_1,$b_0)
1120         $ADDU   $c_2,$t_1
1121         sltu    $at,$c_2,$t_1
1122          $MULTU ($a_2,$b_0)             # mul_add_c(a[2],b[0],c3,c1,c2);
1123         $ADDU   $t_2,$at
1124         $ADDU   $c_3,$t_2
1125         sltu    $c_1,$c_3,$t_2
1126         $ST     $c_2,$BNSZ($a0) # r[1]=c2;
1127
1128         mflo    ($t_1,$a_2,$b_0)
1129         mfhi    ($t_2,$a_2,$b_0)
1130         $ADDU   $c_3,$t_1
1131         sltu    $at,$c_3,$t_1
1132         $MULTU  ($a_1,$b_1)             # mul_add_c(a[1],b[1],c3,c1,c2);
1133         $ADDU   $t_2,$at
1134         $ADDU   $c_1,$t_2
1135         mflo    ($t_1,$a_1,$b_1)
1136         mfhi    ($t_2,$a_1,$b_1)
1137         $ADDU   $c_3,$t_1
1138         sltu    $at,$c_3,$t_1
1139         $MULTU  ($a_0,$b_2)             # mul_add_c(a[0],b[2],c3,c1,c2);
1140         $ADDU   $t_2,$at
1141         $ADDU   $c_1,$t_2
1142         sltu    $c_2,$c_1,$t_2
1143         mflo    ($t_1,$a_0,$b_2)
1144         mfhi    ($t_2,$a_0,$b_2)
1145         $ADDU   $c_3,$t_1
1146         sltu    $at,$c_3,$t_1
1147          $MULTU ($a_0,$b_3)             # mul_add_c(a[0],b[3],c1,c2,c3);
1148         $ADDU   $t_2,$at
1149         $ADDU   $c_1,$t_2
1150         sltu    $at,$c_1,$t_2
1151         $ADDU   $c_2,$at
1152         $ST     $c_3,2*$BNSZ($a0)       # r[2]=c3;
1153
1154         mflo    ($t_1,$a_0,$b_3)
1155         mfhi    ($t_2,$a_0,$b_3)
1156         $ADDU   $c_1,$t_1
1157         sltu    $at,$c_1,$t_1
1158         $MULTU  ($a_1,$b_2)             # mul_add_c(a[1],b[2],c1,c2,c3);
1159         $ADDU   $t_2,$at
1160         $ADDU   $c_2,$t_2
1161         sltu    $c_3,$c_2,$t_2
1162         mflo    ($t_1,$a_1,$b_2)
1163         mfhi    ($t_2,$a_1,$b_2)
1164         $ADDU   $c_1,$t_1
1165         sltu    $at,$c_1,$t_1
1166         $MULTU  ($a_2,$b_1)             # mul_add_c(a[2],b[1],c1,c2,c3);
1167         $ADDU   $t_2,$at
1168         $ADDU   $c_2,$t_2
1169         sltu    $at,$c_2,$t_2
1170         $ADDU   $c_3,$at
1171         mflo    ($t_1,$a_2,$b_1)
1172         mfhi    ($t_2,$a_2,$b_1)
1173         $ADDU   $c_1,$t_1
1174         sltu    $at,$c_1,$t_1
1175         $MULTU  ($a_3,$b_0)             # mul_add_c(a[3],b[0],c1,c2,c3);
1176         $ADDU   $t_2,$at
1177         $ADDU   $c_2,$t_2
1178         sltu    $at,$c_2,$t_2
1179         $ADDU   $c_3,$at
1180         mflo    ($t_1,$a_3,$b_0)
1181         mfhi    ($t_2,$a_3,$b_0)
1182         $ADDU   $c_1,$t_1
1183         sltu    $at,$c_1,$t_1
1184          $MULTU ($a_4,$b_0)             # mul_add_c(a[4],b[0],c2,c3,c1);
1185         $ADDU   $t_2,$at
1186         $ADDU   $c_2,$t_2
1187         sltu    $at,$c_2,$t_2
1188         $ADDU   $c_3,$at
1189         $ST     $c_1,3*$BNSZ($a0)       # r[3]=c1;
1190
1191         mflo    ($t_1,$a_4,$b_0)
1192         mfhi    ($t_2,$a_4,$b_0)
1193         $ADDU   $c_2,$t_1
1194         sltu    $at,$c_2,$t_1
1195         $MULTU  ($a_3,$b_1)             # mul_add_c(a[3],b[1],c2,c3,c1);
1196         $ADDU   $t_2,$at
1197         $ADDU   $c_3,$t_2
1198         sltu    $c_1,$c_3,$t_2
1199         mflo    ($t_1,$a_3,$b_1)
1200         mfhi    ($t_2,$a_3,$b_1)
1201         $ADDU   $c_2,$t_1
1202         sltu    $at,$c_2,$t_1
1203         $MULTU  ($a_2,$b_2)             # mul_add_c(a[2],b[2],c2,c3,c1);
1204         $ADDU   $t_2,$at
1205         $ADDU   $c_3,$t_2
1206         sltu    $at,$c_3,$t_2
1207         $ADDU   $c_1,$at
1208         mflo    ($t_1,$a_2,$b_2)
1209         mfhi    ($t_2,$a_2,$b_2)
1210         $ADDU   $c_2,$t_1
1211         sltu    $at,$c_2,$t_1
1212         $MULTU  ($a_1,$b_3)             # mul_add_c(a[1],b[3],c2,c3,c1);
1213         $ADDU   $t_2,$at
1214         $ADDU   $c_3,$t_2
1215         sltu    $at,$c_3,$t_2
1216         $ADDU   $c_1,$at
1217         mflo    ($t_1,$a_1,$b_3)
1218         mfhi    ($t_2,$a_1,$b_3)
1219         $ADDU   $c_2,$t_1
1220         sltu    $at,$c_2,$t_1
1221         $MULTU  ($a_0,$b_4)             # mul_add_c(a[0],b[4],c2,c3,c1);
1222         $ADDU   $t_2,$at
1223         $ADDU   $c_3,$t_2
1224         sltu    $at,$c_3,$t_2
1225         $ADDU   $c_1,$at
1226         mflo    ($t_1,$a_0,$b_4)
1227         mfhi    ($t_2,$a_0,$b_4)
1228         $ADDU   $c_2,$t_1
1229         sltu    $at,$c_2,$t_1
1230          $MULTU ($a_0,$b_5)             # mul_add_c(a[0],b[5],c3,c1,c2);
1231         $ADDU   $t_2,$at
1232         $ADDU   $c_3,$t_2
1233         sltu    $at,$c_3,$t_2
1234         $ADDU   $c_1,$at
1235         $ST     $c_2,4*$BNSZ($a0)       # r[4]=c2;
1236
1237         mflo    ($t_1,$a_0,$b_5)
1238         mfhi    ($t_2,$a_0,$b_5)
1239         $ADDU   $c_3,$t_1
1240         sltu    $at,$c_3,$t_1
1241         $MULTU  ($a_1,$b_4)             # mul_add_c(a[1],b[4],c3,c1,c2);
1242         $ADDU   $t_2,$at
1243         $ADDU   $c_1,$t_2
1244         sltu    $c_2,$c_1,$t_2
1245         mflo    ($t_1,$a_1,$b_4)
1246         mfhi    ($t_2,$a_1,$b_4)
1247         $ADDU   $c_3,$t_1
1248         sltu    $at,$c_3,$t_1
1249         $MULTU  ($a_2,$b_3)             # mul_add_c(a[2],b[3],c3,c1,c2);
1250         $ADDU   $t_2,$at
1251         $ADDU   $c_1,$t_2
1252         sltu    $at,$c_1,$t_2
1253         $ADDU   $c_2,$at
1254         mflo    ($t_1,$a_2,$b_3)
1255         mfhi    ($t_2,$a_2,$b_3)
1256         $ADDU   $c_3,$t_1
1257         sltu    $at,$c_3,$t_1
1258         $MULTU  ($a_3,$b_2)             # mul_add_c(a[3],b[2],c3,c1,c2);
1259         $ADDU   $t_2,$at
1260         $ADDU   $c_1,$t_2
1261         sltu    $at,$c_1,$t_2
1262         $ADDU   $c_2,$at
1263         mflo    ($t_1,$a_3,$b_2)
1264         mfhi    ($t_2,$a_3,$b_2)
1265         $ADDU   $c_3,$t_1
1266         sltu    $at,$c_3,$t_1
1267         $MULTU  ($a_4,$b_1)             # mul_add_c(a[4],b[1],c3,c1,c2);
1268         $ADDU   $t_2,$at
1269         $ADDU   $c_1,$t_2
1270         sltu    $at,$c_1,$t_2
1271         $ADDU   $c_2,$at
1272         mflo    ($t_1,$a_4,$b_1)
1273         mfhi    ($t_2,$a_4,$b_1)
1274         $ADDU   $c_3,$t_1
1275         sltu    $at,$c_3,$t_1
1276         $MULTU  ($a_5,$b_0)             # mul_add_c(a[5],b[0],c3,c1,c2);
1277         $ADDU   $t_2,$at
1278         $ADDU   $c_1,$t_2
1279         sltu    $at,$c_1,$t_2
1280         $ADDU   $c_2,$at
1281         mflo    ($t_1,$a_5,$b_0)
1282         mfhi    ($t_2,$a_5,$b_0)
1283         $ADDU   $c_3,$t_1
1284         sltu    $at,$c_3,$t_1
1285          $MULTU ($a_6,$b_0)             # mul_add_c(a[6],b[0],c1,c2,c3);
1286         $ADDU   $t_2,$at
1287         $ADDU   $c_1,$t_2
1288         sltu    $at,$c_1,$t_2
1289         $ADDU   $c_2,$at
1290         $ST     $c_3,5*$BNSZ($a0)       # r[5]=c3;
1291
1292         mflo    ($t_1,$a_6,$b_0)
1293         mfhi    ($t_2,$a_6,$b_0)
1294         $ADDU   $c_1,$t_1
1295         sltu    $at,$c_1,$t_1
1296         $MULTU  ($a_5,$b_1)             # mul_add_c(a[5],b[1],c1,c2,c3);
1297         $ADDU   $t_2,$at
1298         $ADDU   $c_2,$t_2
1299         sltu    $c_3,$c_2,$t_2
1300         mflo    ($t_1,$a_5,$b_1)
1301         mfhi    ($t_2,$a_5,$b_1)
1302         $ADDU   $c_1,$t_1
1303         sltu    $at,$c_1,$t_1
1304         $MULTU  ($a_4,$b_2)             # mul_add_c(a[4],b[2],c1,c2,c3);
1305         $ADDU   $t_2,$at
1306         $ADDU   $c_2,$t_2
1307         sltu    $at,$c_2,$t_2
1308         $ADDU   $c_3,$at
1309         mflo    ($t_1,$a_4,$b_2)
1310         mfhi    ($t_2,$a_4,$b_2)
1311         $ADDU   $c_1,$t_1
1312         sltu    $at,$c_1,$t_1
1313         $MULTU  ($a_3,$b_3)             # mul_add_c(a[3],b[3],c1,c2,c3);
1314         $ADDU   $t_2,$at
1315         $ADDU   $c_2,$t_2
1316         sltu    $at,$c_2,$t_2
1317         $ADDU   $c_3,$at
1318         mflo    ($t_1,$a_3,$b_3)
1319         mfhi    ($t_2,$a_3,$b_3)
1320         $ADDU   $c_1,$t_1
1321         sltu    $at,$c_1,$t_1
1322         $MULTU  ($a_2,$b_4)             # mul_add_c(a[2],b[4],c1,c2,c3);
1323         $ADDU   $t_2,$at
1324         $ADDU   $c_2,$t_2
1325         sltu    $at,$c_2,$t_2
1326         $ADDU   $c_3,$at
1327         mflo    ($t_1,$a_2,$b_4)
1328         mfhi    ($t_2,$a_2,$b_4)
1329         $ADDU   $c_1,$t_1
1330         sltu    $at,$c_1,$t_1
1331         $MULTU  ($a_1,$b_5)             # mul_add_c(a[1],b[5],c1,c2,c3);
1332         $ADDU   $t_2,$at
1333         $ADDU   $c_2,$t_2
1334         sltu    $at,$c_2,$t_2
1335         $ADDU   $c_3,$at
1336         mflo    ($t_1,$a_1,$b_5)
1337         mfhi    ($t_2,$a_1,$b_5)
1338         $ADDU   $c_1,$t_1
1339         sltu    $at,$c_1,$t_1
1340         $MULTU  ($a_0,$b_6)             # mul_add_c(a[0],b[6],c1,c2,c3);
1341         $ADDU   $t_2,$at
1342         $ADDU   $c_2,$t_2
1343         sltu    $at,$c_2,$t_2
1344         $ADDU   $c_3,$at
1345         mflo    ($t_1,$a_0,$b_6)
1346         mfhi    ($t_2,$a_0,$b_6)
1347         $ADDU   $c_1,$t_1
1348         sltu    $at,$c_1,$t_1
1349          $MULTU ($a_0,$b_7)             # mul_add_c(a[0],b[7],c2,c3,c1);
1350         $ADDU   $t_2,$at
1351         $ADDU   $c_2,$t_2
1352         sltu    $at,$c_2,$t_2
1353         $ADDU   $c_3,$at
1354         $ST     $c_1,6*$BNSZ($a0)       # r[6]=c1;
1355
1356         mflo    ($t_1,$a_0,$b_7)
1357         mfhi    ($t_2,$a_0,$b_7)
1358         $ADDU   $c_2,$t_1
1359         sltu    $at,$c_2,$t_1
1360         $MULTU  ($a_1,$b_6)             # mul_add_c(a[1],b[6],c2,c3,c1);
1361         $ADDU   $t_2,$at
1362         $ADDU   $c_3,$t_2
1363         sltu    $c_1,$c_3,$t_2
1364         mflo    ($t_1,$a_1,$b_6)
1365         mfhi    ($t_2,$a_1,$b_6)
1366         $ADDU   $c_2,$t_1
1367         sltu    $at,$c_2,$t_1
1368         $MULTU  ($a_2,$b_5)             # mul_add_c(a[2],b[5],c2,c3,c1);
1369         $ADDU   $t_2,$at
1370         $ADDU   $c_3,$t_2
1371         sltu    $at,$c_3,$t_2
1372         $ADDU   $c_1,$at
1373         mflo    ($t_1,$a_2,$b_5)
1374         mfhi    ($t_2,$a_2,$b_5)
1375         $ADDU   $c_2,$t_1
1376         sltu    $at,$c_2,$t_1
1377         $MULTU  ($a_3,$b_4)             # mul_add_c(a[3],b[4],c2,c3,c1);
1378         $ADDU   $t_2,$at
1379         $ADDU   $c_3,$t_2
1380         sltu    $at,$c_3,$t_2
1381         $ADDU   $c_1,$at
1382         mflo    ($t_1,$a_3,$b_4)
1383         mfhi    ($t_2,$a_3,$b_4)
1384         $ADDU   $c_2,$t_1
1385         sltu    $at,$c_2,$t_1
1386         $MULTU  ($a_4,$b_3)             # mul_add_c(a[4],b[3],c2,c3,c1);
1387         $ADDU   $t_2,$at
1388         $ADDU   $c_3,$t_2
1389         sltu    $at,$c_3,$t_2
1390         $ADDU   $c_1,$at
1391         mflo    ($t_1,$a_4,$b_3)
1392         mfhi    ($t_2,$a_4,$b_3)
1393         $ADDU   $c_2,$t_1
1394         sltu    $at,$c_2,$t_1
1395         $MULTU  ($a_5,$b_2)             # mul_add_c(a[5],b[2],c2,c3,c1);
1396         $ADDU   $t_2,$at
1397         $ADDU   $c_3,$t_2
1398         sltu    $at,$c_3,$t_2
1399         $ADDU   $c_1,$at
1400         mflo    ($t_1,$a_5,$b_2)
1401         mfhi    ($t_2,$a_5,$b_2)
1402         $ADDU   $c_2,$t_1
1403         sltu    $at,$c_2,$t_1
1404         $MULTU  ($a_6,$b_1)             # mul_add_c(a[6],b[1],c2,c3,c1);
1405         $ADDU   $t_2,$at
1406         $ADDU   $c_3,$t_2
1407         sltu    $at,$c_3,$t_2
1408         $ADDU   $c_1,$at
1409         mflo    ($t_1,$a_6,$b_1)
1410         mfhi    ($t_2,$a_6,$b_1)
1411         $ADDU   $c_2,$t_1
1412         sltu    $at,$c_2,$t_1
1413         $MULTU  ($a_7,$b_0)             # mul_add_c(a[7],b[0],c2,c3,c1);
1414         $ADDU   $t_2,$at
1415         $ADDU   $c_3,$t_2
1416         sltu    $at,$c_3,$t_2
1417         $ADDU   $c_1,$at
1418         mflo    ($t_1,$a_7,$b_0)
1419         mfhi    ($t_2,$a_7,$b_0)
1420         $ADDU   $c_2,$t_1
1421         sltu    $at,$c_2,$t_1
1422          $MULTU ($a_7,$b_1)             # mul_add_c(a[7],b[1],c3,c1,c2);
1423         $ADDU   $t_2,$at
1424         $ADDU   $c_3,$t_2
1425         sltu    $at,$c_3,$t_2
1426         $ADDU   $c_1,$at
1427         $ST     $c_2,7*$BNSZ($a0)       # r[7]=c2;
1428
1429         mflo    ($t_1,$a_7,$b_1)
1430         mfhi    ($t_2,$a_7,$b_1)
1431         $ADDU   $c_3,$t_1
1432         sltu    $at,$c_3,$t_1
1433         $MULTU  ($a_6,$b_2)             # mul_add_c(a[6],b[2],c3,c1,c2);
1434         $ADDU   $t_2,$at
1435         $ADDU   $c_1,$t_2
1436         sltu    $c_2,$c_1,$t_2
1437         mflo    ($t_1,$a_6,$b_2)
1438         mfhi    ($t_2,$a_6,$b_2)
1439         $ADDU   $c_3,$t_1
1440         sltu    $at,$c_3,$t_1
1441         $MULTU  ($a_5,$b_3)             # mul_add_c(a[5],b[3],c3,c1,c2);
1442         $ADDU   $t_2,$at
1443         $ADDU   $c_1,$t_2
1444         sltu    $at,$c_1,$t_2
1445         $ADDU   $c_2,$at
1446         mflo    ($t_1,$a_5,$b_3)
1447         mfhi    ($t_2,$a_5,$b_3)
1448         $ADDU   $c_3,$t_1
1449         sltu    $at,$c_3,$t_1
1450         $MULTU  ($a_4,$b_4)             # mul_add_c(a[4],b[4],c3,c1,c2);
1451         $ADDU   $t_2,$at
1452         $ADDU   $c_1,$t_2
1453         sltu    $at,$c_1,$t_2
1454         $ADDU   $c_2,$at
1455         mflo    ($t_1,$a_4,$b_4)
1456         mfhi    ($t_2,$a_4,$b_4)
1457         $ADDU   $c_3,$t_1
1458         sltu    $at,$c_3,$t_1
1459         $MULTU  ($a_3,$b_5)             # mul_add_c(a[3],b[5],c3,c1,c2);
1460         $ADDU   $t_2,$at
1461         $ADDU   $c_1,$t_2
1462         sltu    $at,$c_1,$t_2
1463         $ADDU   $c_2,$at
1464         mflo    ($t_1,$a_3,$b_5)
1465         mfhi    ($t_2,$a_3,$b_5)
1466         $ADDU   $c_3,$t_1
1467         sltu    $at,$c_3,$t_1
1468         $MULTU  ($a_2,$b_6)             # mul_add_c(a[2],b[6],c3,c1,c2);
1469         $ADDU   $t_2,$at
1470         $ADDU   $c_1,$t_2
1471         sltu    $at,$c_1,$t_2
1472         $ADDU   $c_2,$at
1473         mflo    ($t_1,$a_2,$b_6)
1474         mfhi    ($t_2,$a_2,$b_6)
1475         $ADDU   $c_3,$t_1
1476         sltu    $at,$c_3,$t_1
1477         $MULTU  ($a_1,$b_7)             # mul_add_c(a[1],b[7],c3,c1,c2);
1478         $ADDU   $t_2,$at
1479         $ADDU   $c_1,$t_2
1480         sltu    $at,$c_1,$t_2
1481         $ADDU   $c_2,$at
1482         mflo    ($t_1,$a_1,$b_7)
1483         mfhi    ($t_2,$a_1,$b_7)
1484         $ADDU   $c_3,$t_1
1485         sltu    $at,$c_3,$t_1
1486          $MULTU ($a_2,$b_7)             # mul_add_c(a[2],b[7],c1,c2,c3);
1487         $ADDU   $t_2,$at
1488         $ADDU   $c_1,$t_2
1489         sltu    $at,$c_1,$t_2
1490         $ADDU   $c_2,$at
1491         $ST     $c_3,8*$BNSZ($a0)       # r[8]=c3;
1492
1493         mflo    ($t_1,$a_2,$b_7)
1494         mfhi    ($t_2,$a_2,$b_7)
1495         $ADDU   $c_1,$t_1
1496         sltu    $at,$c_1,$t_1
1497         $MULTU  ($a_3,$b_6)             # mul_add_c(a[3],b[6],c1,c2,c3);
1498         $ADDU   $t_2,$at
1499         $ADDU   $c_2,$t_2
1500         sltu    $c_3,$c_2,$t_2
1501         mflo    ($t_1,$a_3,$b_6)
1502         mfhi    ($t_2,$a_3,$b_6)
1503         $ADDU   $c_1,$t_1
1504         sltu    $at,$c_1,$t_1
1505         $MULTU  ($a_4,$b_5)             # mul_add_c(a[4],b[5],c1,c2,c3);
1506         $ADDU   $t_2,$at
1507         $ADDU   $c_2,$t_2
1508         sltu    $at,$c_2,$t_2
1509         $ADDU   $c_3,$at
1510         mflo    ($t_1,$a_4,$b_5)
1511         mfhi    ($t_2,$a_4,$b_5)
1512         $ADDU   $c_1,$t_1
1513         sltu    $at,$c_1,$t_1
1514         $MULTU  ($a_5,$b_4)             # mul_add_c(a[5],b[4],c1,c2,c3);
1515         $ADDU   $t_2,$at
1516         $ADDU   $c_2,$t_2
1517         sltu    $at,$c_2,$t_2
1518         $ADDU   $c_3,$at
1519         mflo    ($t_1,$a_5,$b_4)
1520         mfhi    ($t_2,$a_5,$b_4)
1521         $ADDU   $c_1,$t_1
1522         sltu    $at,$c_1,$t_1
1523         $MULTU  ($a_6,$b_3)             # mul_add_c(a[6],b[3],c1,c2,c3);
1524         $ADDU   $t_2,$at
1525         $ADDU   $c_2,$t_2
1526         sltu    $at,$c_2,$t_2
1527         $ADDU   $c_3,$at
1528         mflo    ($t_1,$a_6,$b_3)
1529         mfhi    ($t_2,$a_6,$b_3)
1530         $ADDU   $c_1,$t_1
1531         sltu    $at,$c_1,$t_1
1532         $MULTU  ($a_7,$b_2)             # mul_add_c(a[7],b[2],c1,c2,c3);
1533         $ADDU   $t_2,$at
1534         $ADDU   $c_2,$t_2
1535         sltu    $at,$c_2,$t_2
1536         $ADDU   $c_3,$at
1537         mflo    ($t_1,$a_7,$b_2)
1538         mfhi    ($t_2,$a_7,$b_2)
1539         $ADDU   $c_1,$t_1
1540         sltu    $at,$c_1,$t_1
1541          $MULTU ($a_7,$b_3)             # mul_add_c(a[7],b[3],c2,c3,c1);
1542         $ADDU   $t_2,$at
1543         $ADDU   $c_2,$t_2
1544         sltu    $at,$c_2,$t_2
1545         $ADDU   $c_3,$at
1546         $ST     $c_1,9*$BNSZ($a0)       # r[9]=c1;
1547
1548         mflo    ($t_1,$a_7,$b_3)
1549         mfhi    ($t_2,$a_7,$b_3)
1550         $ADDU   $c_2,$t_1
1551         sltu    $at,$c_2,$t_1
1552         $MULTU  ($a_6,$b_4)             # mul_add_c(a[6],b[4],c2,c3,c1);
1553         $ADDU   $t_2,$at
1554         $ADDU   $c_3,$t_2
1555         sltu    $c_1,$c_3,$t_2
1556         mflo    ($t_1,$a_6,$b_4)
1557         mfhi    ($t_2,$a_6,$b_4)
1558         $ADDU   $c_2,$t_1
1559         sltu    $at,$c_2,$t_1
1560         $MULTU  ($a_5,$b_5)             # mul_add_c(a[5],b[5],c2,c3,c1);
1561         $ADDU   $t_2,$at
1562         $ADDU   $c_3,$t_2
1563         sltu    $at,$c_3,$t_2
1564         $ADDU   $c_1,$at
1565         mflo    ($t_1,$a_5,$b_5)
1566         mfhi    ($t_2,$a_5,$b_5)
1567         $ADDU   $c_2,$t_1
1568         sltu    $at,$c_2,$t_1
1569         $MULTU  ($a_4,$b_6)             # mul_add_c(a[4],b[6],c2,c3,c1);
1570         $ADDU   $t_2,$at
1571         $ADDU   $c_3,$t_2
1572         sltu    $at,$c_3,$t_2
1573         $ADDU   $c_1,$at
1574         mflo    ($t_1,$a_4,$b_6)
1575         mfhi    ($t_2,$a_4,$b_6)
1576         $ADDU   $c_2,$t_1
1577         sltu    $at,$c_2,$t_1
1578         $MULTU  ($a_3,$b_7)             # mul_add_c(a[3],b[7],c2,c3,c1);
1579         $ADDU   $t_2,$at
1580         $ADDU   $c_3,$t_2
1581         sltu    $at,$c_3,$t_2
1582         $ADDU   $c_1,$at
1583         mflo    ($t_1,$a_3,$b_7)
1584         mfhi    ($t_2,$a_3,$b_7)
1585         $ADDU   $c_2,$t_1
1586         sltu    $at,$c_2,$t_1
1587         $MULTU  ($a_4,$b_7)             # mul_add_c(a[4],b[7],c3,c1,c2);
1588         $ADDU   $t_2,$at
1589         $ADDU   $c_3,$t_2
1590         sltu    $at,$c_3,$t_2
1591         $ADDU   $c_1,$at
1592         $ST     $c_2,10*$BNSZ($a0)      # r[10]=c2;
1593
1594         mflo    ($t_1,$a_4,$b_7)
1595         mfhi    ($t_2,$a_4,$b_7)
1596         $ADDU   $c_3,$t_1
1597         sltu    $at,$c_3,$t_1
1598         $MULTU  ($a_5,$b_6)             # mul_add_c(a[5],b[6],c3,c1,c2);
1599         $ADDU   $t_2,$at
1600         $ADDU   $c_1,$t_2
1601         sltu    $c_2,$c_1,$t_2
1602         mflo    ($t_1,$a_5,$b_6)
1603         mfhi    ($t_2,$a_5,$b_6)
1604         $ADDU   $c_3,$t_1
1605         sltu    $at,$c_3,$t_1
1606         $MULTU  ($a_6,$b_5)             # mul_add_c(a[6],b[5],c3,c1,c2);
1607         $ADDU   $t_2,$at
1608         $ADDU   $c_1,$t_2
1609         sltu    $at,$c_1,$t_2
1610         $ADDU   $c_2,$at
1611         mflo    ($t_1,$a_6,$b_5)
1612         mfhi    ($t_2,$a_6,$b_5)
1613         $ADDU   $c_3,$t_1
1614         sltu    $at,$c_3,$t_1
1615         $MULTU  ($a_7,$b_4)             # mul_add_c(a[7],b[4],c3,c1,c2);
1616         $ADDU   $t_2,$at
1617         $ADDU   $c_1,$t_2
1618         sltu    $at,$c_1,$t_2
1619         $ADDU   $c_2,$at
1620         mflo    ($t_1,$a_7,$b_4)
1621         mfhi    ($t_2,$a_7,$b_4)
1622         $ADDU   $c_3,$t_1
1623         sltu    $at,$c_3,$t_1
1624          $MULTU ($a_7,$b_5)             # mul_add_c(a[7],b[5],c1,c2,c3);
1625         $ADDU   $t_2,$at
1626         $ADDU   $c_1,$t_2
1627         sltu    $at,$c_1,$t_2
1628         $ADDU   $c_2,$at
1629         $ST     $c_3,11*$BNSZ($a0)      # r[11]=c3;
1630
1631         mflo    ($t_1,$a_7,$b_5)
1632         mfhi    ($t_2,$a_7,$b_5)
1633         $ADDU   $c_1,$t_1
1634         sltu    $at,$c_1,$t_1
1635         $MULTU  ($a_6,$b_6)             # mul_add_c(a[6],b[6],c1,c2,c3);
1636         $ADDU   $t_2,$at
1637         $ADDU   $c_2,$t_2
1638         sltu    $c_3,$c_2,$t_2
1639         mflo    ($t_1,$a_6,$b_6)
1640         mfhi    ($t_2,$a_6,$b_6)
1641         $ADDU   $c_1,$t_1
1642         sltu    $at,$c_1,$t_1
1643         $MULTU  ($a_5,$b_7)             # mul_add_c(a[5],b[7],c1,c2,c3);
1644         $ADDU   $t_2,$at
1645         $ADDU   $c_2,$t_2
1646         sltu    $at,$c_2,$t_2
1647         $ADDU   $c_3,$at
1648         mflo    ($t_1,$a_5,$b_7)
1649         mfhi    ($t_2,$a_5,$b_7)
1650         $ADDU   $c_1,$t_1
1651         sltu    $at,$c_1,$t_1
1652          $MULTU ($a_6,$b_7)             # mul_add_c(a[6],b[7],c2,c3,c1);
1653         $ADDU   $t_2,$at
1654         $ADDU   $c_2,$t_2
1655         sltu    $at,$c_2,$t_2
1656         $ADDU   $c_3,$at
1657         $ST     $c_1,12*$BNSZ($a0)      # r[12]=c1;
1658
1659         mflo    ($t_1,$a_6,$b_7)
1660         mfhi    ($t_2,$a_6,$b_7)
1661         $ADDU   $c_2,$t_1
1662         sltu    $at,$c_2,$t_1
1663         $MULTU  ($a_7,$b_6)             # mul_add_c(a[7],b[6],c2,c3,c1);
1664         $ADDU   $t_2,$at
1665         $ADDU   $c_3,$t_2
1666         sltu    $c_1,$c_3,$t_2
1667         mflo    ($t_1,$a_7,$b_6)
1668         mfhi    ($t_2,$a_7,$b_6)
1669         $ADDU   $c_2,$t_1
1670         sltu    $at,$c_2,$t_1
1671         $MULTU  ($a_7,$b_7)             # mul_add_c(a[7],b[7],c3,c1,c2);
1672         $ADDU   $t_2,$at
1673         $ADDU   $c_3,$t_2
1674         sltu    $at,$c_3,$t_2
1675         $ADDU   $c_1,$at
1676         $ST     $c_2,13*$BNSZ($a0)      # r[13]=c2;
1677
1678         mflo    ($t_1,$a_7,$b_7)
1679         mfhi    ($t_2,$a_7,$b_7)
1680         $ADDU   $c_3,$t_1
1681         sltu    $at,$c_3,$t_1
1682         $ADDU   $t_2,$at
1683         $ADDU   $c_1,$t_2
1684         $ST     $c_3,14*$BNSZ($a0)      # r[14]=c3;
1685         $ST     $c_1,15*$BNSZ($a0)      # r[15]=c1;
1686
1687         .set    noreorder
1688 ___
1689 $code.=<<___ if ($flavour =~ /nubi/i);
1690         $REG_L  $s5,10*$SZREG($sp)
1691         $REG_L  $s4,9*$SZREG($sp)
1692         $REG_L  $s3,8*$SZREG($sp)
1693         $REG_L  $s2,7*$SZREG($sp)
1694         $REG_L  $s1,6*$SZREG($sp)
1695         $REG_L  $s0,5*$SZREG($sp)
1696         $REG_L  $t3,4*$SZREG($sp)
1697         $REG_L  $t2,3*$SZREG($sp)
1698         $REG_L  $t1,2*$SZREG($sp)
1699         $REG_L  $t0,1*$SZREG($sp)
1700         $REG_L  $gp,0*$SZREG($sp)
1701         jr      $ra
1702         $PTR_ADD $sp,12*$SZREG
1703 ___
1704 $code.=<<___ if ($flavour !~ /nubi/i);
1705         $REG_L  $s5,5*$SZREG($sp)
1706         $REG_L  $s4,4*$SZREG($sp)
1707         $REG_L  $s3,3*$SZREG($sp)
1708         $REG_L  $s2,2*$SZREG($sp)
1709         $REG_L  $s1,1*$SZREG($sp)
1710         $REG_L  $s0,0*$SZREG($sp)
1711         jr      $ra
1712         $PTR_ADD $sp,6*$SZREG
1713 ___
1714 $code.=<<___;
1715 .end    bn_mul_comba8
1716
1717 .align  5
1718 .globl  bn_mul_comba4
1719 .ent    bn_mul_comba4
1720 bn_mul_comba4:
1721 ___
1722 $code.=<<___ if ($flavour =~ /nubi/i);
1723         .frame  $sp,6*$SZREG,$ra
1724         .mask   0x8000f008,-$SZREG
1725         .set    noreorder
1726         $PTR_SUB $sp,6*$SZREG
1727         $REG_S  $ra,5*$SZREG($sp)
1728         $REG_S  $t3,4*$SZREG($sp)
1729         $REG_S  $t2,3*$SZREG($sp)
1730         $REG_S  $t1,2*$SZREG($sp)
1731         $REG_S  $t0,1*$SZREG($sp)
1732         $REG_S  $gp,0*$SZREG($sp)
1733 ___
1734 $code.=<<___;
1735         .set    reorder
1736         $LD     $a_0,0($a1)
1737         $LD     $b_0,0($a2)
1738         $LD     $a_1,$BNSZ($a1)
1739         $LD     $a_2,2*$BNSZ($a1)
1740         $MULTU  ($a_0,$b_0)             # mul_add_c(a[0],b[0],c1,c2,c3);
1741         $LD     $a_3,3*$BNSZ($a1)
1742         $LD     $b_1,$BNSZ($a2)
1743         $LD     $b_2,2*$BNSZ($a2)
1744         $LD     $b_3,3*$BNSZ($a2)
1745         mflo    ($c_1,$a_0,$b_0)
1746         mfhi    ($c_2,$a_0,$b_0)
1747         $ST     $c_1,0($a0)
1748
1749         $MULTU  ($a_0,$b_1)             # mul_add_c(a[0],b[1],c2,c3,c1);
1750         mflo    ($t_1,$a_0,$b_1)
1751         mfhi    ($t_2,$a_0,$b_1)
1752         $ADDU   $c_2,$t_1
1753         sltu    $at,$c_2,$t_1
1754         $MULTU  ($a_1,$b_0)             # mul_add_c(a[1],b[0],c2,c3,c1);
1755         $ADDU   $c_3,$t_2,$at
1756         mflo    ($t_1,$a_1,$b_0)
1757         mfhi    ($t_2,$a_1,$b_0)
1758         $ADDU   $c_2,$t_1
1759         sltu    $at,$c_2,$t_1
1760          $MULTU ($a_2,$b_0)             # mul_add_c(a[2],b[0],c3,c1,c2);
1761         $ADDU   $t_2,$at
1762         $ADDU   $c_3,$t_2
1763         sltu    $c_1,$c_3,$t_2
1764         $ST     $c_2,$BNSZ($a0)
1765
1766         mflo    ($t_1,$a_2,$b_0)
1767         mfhi    ($t_2,$a_2,$b_0)
1768         $ADDU   $c_3,$t_1
1769         sltu    $at,$c_3,$t_1
1770         $MULTU  ($a_1,$b_1)             # mul_add_c(a[1],b[1],c3,c1,c2);
1771         $ADDU   $t_2,$at
1772         $ADDU   $c_1,$t_2
1773         mflo    ($t_1,$a_1,$b_1)
1774         mfhi    ($t_2,$a_1,$b_1)
1775         $ADDU   $c_3,$t_1
1776         sltu    $at,$c_3,$t_1
1777         $MULTU  ($a_0,$b_2)             # mul_add_c(a[0],b[2],c3,c1,c2);
1778         $ADDU   $t_2,$at
1779         $ADDU   $c_1,$t_2
1780         sltu    $c_2,$c_1,$t_2
1781         mflo    ($t_1,$a_0,$b_2)
1782         mfhi    ($t_2,$a_0,$b_2)
1783         $ADDU   $c_3,$t_1
1784         sltu    $at,$c_3,$t_1
1785          $MULTU ($a_0,$b_3)             # mul_add_c(a[0],b[3],c1,c2,c3);
1786         $ADDU   $t_2,$at
1787         $ADDU   $c_1,$t_2
1788         sltu    $at,$c_1,$t_2
1789         $ADDU   $c_2,$at
1790         $ST     $c_3,2*$BNSZ($a0)
1791
1792         mflo    ($t_1,$a_0,$b_3)
1793         mfhi    ($t_2,$a_0,$b_3)
1794         $ADDU   $c_1,$t_1
1795         sltu    $at,$c_1,$t_1
1796         $MULTU  ($a_1,$b_2)             # mul_add_c(a[1],b[2],c1,c2,c3);
1797         $ADDU   $t_2,$at
1798         $ADDU   $c_2,$t_2
1799         sltu    $c_3,$c_2,$t_2
1800         mflo    ($t_1,$a_1,$b_2)
1801         mfhi    ($t_2,$a_1,$b_2)
1802         $ADDU   $c_1,$t_1
1803         sltu    $at,$c_1,$t_1
1804         $MULTU  ($a_2,$b_1)             # mul_add_c(a[2],b[1],c1,c2,c3);
1805         $ADDU   $t_2,$at
1806         $ADDU   $c_2,$t_2
1807         sltu    $at,$c_2,$t_2
1808         $ADDU   $c_3,$at
1809         mflo    ($t_1,$a_2,$b_1)
1810         mfhi    ($t_2,$a_2,$b_1)
1811         $ADDU   $c_1,$t_1
1812         sltu    $at,$c_1,$t_1
1813         $MULTU  ($a_3,$b_0)             # mul_add_c(a[3],b[0],c1,c2,c3);
1814         $ADDU   $t_2,$at
1815         $ADDU   $c_2,$t_2
1816         sltu    $at,$c_2,$t_2
1817         $ADDU   $c_3,$at
1818         mflo    ($t_1,$a_3,$b_0)
1819         mfhi    ($t_2,$a_3,$b_0)
1820         $ADDU   $c_1,$t_1
1821         sltu    $at,$c_1,$t_1
1822          $MULTU ($a_3,$b_1)             # mul_add_c(a[3],b[1],c2,c3,c1);
1823         $ADDU   $t_2,$at
1824         $ADDU   $c_2,$t_2
1825         sltu    $at,$c_2,$t_2
1826         $ADDU   $c_3,$at
1827         $ST     $c_1,3*$BNSZ($a0)
1828
1829         mflo    ($t_1,$a_3,$b_1)
1830         mfhi    ($t_2,$a_3,$b_1)
1831         $ADDU   $c_2,$t_1
1832         sltu    $at,$c_2,$t_1
1833         $MULTU  ($a_2,$b_2)             # mul_add_c(a[2],b[2],c2,c3,c1);
1834         $ADDU   $t_2,$at
1835         $ADDU   $c_3,$t_2
1836         sltu    $c_1,$c_3,$t_2
1837         mflo    ($t_1,$a_2,$b_2)
1838         mfhi    ($t_2,$a_2,$b_2)
1839         $ADDU   $c_2,$t_1
1840         sltu    $at,$c_2,$t_1
1841         $MULTU  ($a_1,$b_3)             # mul_add_c(a[1],b[3],c2,c3,c1);
1842         $ADDU   $t_2,$at
1843         $ADDU   $c_3,$t_2
1844         sltu    $at,$c_3,$t_2
1845         $ADDU   $c_1,$at
1846         mflo    ($t_1,$a_1,$b_3)
1847         mfhi    ($t_2,$a_1,$b_3)
1848         $ADDU   $c_2,$t_1
1849         sltu    $at,$c_2,$t_1
1850          $MULTU ($a_2,$b_3)             # mul_add_c(a[2],b[3],c3,c1,c2);
1851         $ADDU   $t_2,$at
1852         $ADDU   $c_3,$t_2
1853         sltu    $at,$c_3,$t_2
1854         $ADDU   $c_1,$at
1855         $ST     $c_2,4*$BNSZ($a0)
1856
1857         mflo    ($t_1,$a_2,$b_3)
1858         mfhi    ($t_2,$a_2,$b_3)
1859         $ADDU   $c_3,$t_1
1860         sltu    $at,$c_3,$t_1
1861         $MULTU  ($a_3,$b_2)             # mul_add_c(a[3],b[2],c3,c1,c2);
1862         $ADDU   $t_2,$at
1863         $ADDU   $c_1,$t_2
1864         sltu    $c_2,$c_1,$t_2
1865         mflo    ($t_1,$a_3,$b_2)
1866         mfhi    ($t_2,$a_3,$b_2)
1867         $ADDU   $c_3,$t_1
1868         sltu    $at,$c_3,$t_1
1869          $MULTU ($a_3,$b_3)             # mul_add_c(a[3],b[3],c1,c2,c3);
1870         $ADDU   $t_2,$at
1871         $ADDU   $c_1,$t_2
1872         sltu    $at,$c_1,$t_2
1873         $ADDU   $c_2,$at
1874         $ST     $c_3,5*$BNSZ($a0)
1875
1876         mflo    ($t_1,$a_3,$b_3)
1877         mfhi    ($t_2,$a_3,$b_3)
1878         $ADDU   $c_1,$t_1
1879         sltu    $at,$c_1,$t_1
1880         $ADDU   $t_2,$at
1881         $ADDU   $c_2,$t_2
1882         $ST     $c_1,6*$BNSZ($a0)
1883         $ST     $c_2,7*$BNSZ($a0)
1884
1885         .set    noreorder
1886 ___
1887 $code.=<<___ if ($flavour =~ /nubi/i);
1888         $REG_L  $t3,4*$SZREG($sp)
1889         $REG_L  $t2,3*$SZREG($sp)
1890         $REG_L  $t1,2*$SZREG($sp)
1891         $REG_L  $t0,1*$SZREG($sp)
1892         $REG_L  $gp,0*$SZREG($sp)
1893         $PTR_ADD $sp,6*$SZREG
1894 ___
1895 $code.=<<___;
1896         jr      $ra
1897         nop
1898 .end    bn_mul_comba4
1899 ___
1900
1901 ($a_4,$a_5,$a_6,$a_7)=($b_0,$b_1,$b_2,$b_3);
1902
1903 sub add_c2 () {
1904 my ($hi,$lo,$c0,$c1,$c2,
1905     $warm,      # !$warm denotes first call with specific sequence of
1906                 # $c_[XYZ] when there is no Z-carry to accumulate yet;
1907     $an,$bn     # these two are arguments for multiplication which
1908                 # result is used in *next* step [which is why it's
1909                 # commented as "forward multiplication" below];
1910     )=@_;
1911 $code.=<<___;
1912         $ADDU   $c0,$lo
1913         sltu    $at,$c0,$lo
1914          $MULTU ($an,$bn)               # forward multiplication
1915         $ADDU   $c0,$lo
1916         $ADDU   $at,$hi
1917         sltu    $lo,$c0,$lo
1918         $ADDU   $c1,$at
1919         $ADDU   $hi,$lo
1920 ___
1921 $code.=<<___    if (!$warm);
1922         sltu    $c2,$c1,$at
1923         $ADDU   $c1,$hi
1924 ___
1925 $code.=<<___    if ($warm);
1926         sltu    $at,$c1,$at
1927         $ADDU   $c1,$hi
1928         $ADDU   $c2,$at
1929 ___
1930 $code.=<<___;
1931         sltu    $hi,$c1,$hi
1932         $ADDU   $c2,$hi
1933         mflo    ($lo,$an,$bn)
1934         mfhi    ($hi,$an,$bn)
1935 ___
1936 }
1937
1938 $code.=<<___;
1939
1940 .align  5
1941 .globl  bn_sqr_comba8
1942 .ent    bn_sqr_comba8
1943 bn_sqr_comba8:
1944 ___
1945 $code.=<<___ if ($flavour =~ /nubi/i);
1946         .frame  $sp,6*$SZREG,$ra
1947         .mask   0x8000f008,-$SZREG
1948         .set    noreorder
1949         $PTR_SUB $sp,6*$SZREG
1950         $REG_S  $ra,5*$SZREG($sp)
1951         $REG_S  $t3,4*$SZREG($sp)
1952         $REG_S  $t2,3*$SZREG($sp)
1953         $REG_S  $t1,2*$SZREG($sp)
1954         $REG_S  $t0,1*$SZREG($sp)
1955         $REG_S  $gp,0*$SZREG($sp)
1956 ___
1957 $code.=<<___;
1958         .set    reorder
1959         $LD     $a_0,0($a1)
1960         $LD     $a_1,$BNSZ($a1)
1961         $LD     $a_2,2*$BNSZ($a1)
1962         $LD     $a_3,3*$BNSZ($a1)
1963
1964         $MULTU  ($a_0,$a_0)             # mul_add_c(a[0],b[0],c1,c2,c3);
1965         $LD     $a_4,4*$BNSZ($a1)
1966         $LD     $a_5,5*$BNSZ($a1)
1967         $LD     $a_6,6*$BNSZ($a1)
1968         $LD     $a_7,7*$BNSZ($a1)
1969         mflo    ($c_1,$a_0,$a_0)
1970         mfhi    ($c_2,$a_0,$a_0)
1971         $ST     $c_1,0($a0)
1972
1973         $MULTU  ($a_0,$a_1)             # mul_add_c2(a[0],b[1],c2,c3,c1);
1974         mflo    ($t_1,$a_0,$a_1)
1975         mfhi    ($t_2,$a_0,$a_1)
1976         slt     $c_1,$t_2,$zero
1977         $SLL    $t_2,1
1978          $MULTU ($a_2,$a_0)             # mul_add_c2(a[2],b[0],c3,c1,c2);
1979         slt     $a2,$t_1,$zero
1980         $ADDU   $t_2,$a2
1981         $SLL    $t_1,1
1982         $ADDU   $c_2,$t_1
1983         sltu    $at,$c_2,$t_1
1984         $ADDU   $c_3,$t_2,$at
1985         $ST     $c_2,$BNSZ($a0)
1986         mflo    ($t_1,$a_2,$a_0)
1987         mfhi    ($t_2,$a_2,$a_0)
1988 ___
1989         &add_c2($t_2,$t_1,$c_3,$c_1,$c_2,0,
1990                 $a_1,$a_1);             # mul_add_c(a[1],b[1],c3,c1,c2);
1991 $code.=<<___;
1992         $ADDU   $c_3,$t_1
1993         sltu    $at,$c_3,$t_1
1994          $MULTU ($a_0,$a_3)             # mul_add_c2(a[0],b[3],c1,c2,c3);
1995         $ADDU   $t_2,$at
1996         $ADDU   $c_1,$t_2
1997         sltu    $at,$c_1,$t_2
1998         $ADDU   $c_2,$at
1999         $ST     $c_3,2*$BNSZ($a0)
2000         mflo    ($t_1,$a_0,$a_3)
2001         mfhi    ($t_2,$a_0,$a_3)
2002 ___
2003         &add_c2($t_2,$t_1,$c_1,$c_2,$c_3,0,
2004                 $a_1,$a_2);             # mul_add_c2(a[1],b[2],c1,c2,c3);
2005         &add_c2($t_2,$t_1,$c_1,$c_2,$c_3,1,
2006                 $a_4,$a_0);             # mul_add_c2(a[4],b[0],c2,c3,c1);
2007 $code.=<<___;
2008         $ST     $c_1,3*$BNSZ($a0)
2009 ___
2010         &add_c2($t_2,$t_1,$c_2,$c_3,$c_1,0,
2011                 $a_3,$a_1);             # mul_add_c2(a[3],b[1],c2,c3,c1);
2012         &add_c2($t_2,$t_1,$c_2,$c_3,$c_1,1,
2013                 $a_2,$a_2);             # mul_add_c(a[2],b[2],c2,c3,c1);
2014 $code.=<<___;
2015         $ADDU   $c_2,$t_1
2016         sltu    $at,$c_2,$t_1
2017          $MULTU ($a_0,$a_5)             # mul_add_c2(a[0],b[5],c3,c1,c2);
2018         $ADDU   $t_2,$at
2019         $ADDU   $c_3,$t_2
2020         sltu    $at,$c_3,$t_2
2021         $ADDU   $c_1,$at
2022         $ST     $c_2,4*$BNSZ($a0)
2023         mflo    ($t_1,$a_0,$a_5)
2024         mfhi    ($t_2,$a_0,$a_5)
2025 ___
2026         &add_c2($t_2,$t_1,$c_3,$c_1,$c_2,0,
2027                 $a_1,$a_4);             # mul_add_c2(a[1],b[4],c3,c1,c2);
2028         &add_c2($t_2,$t_1,$c_3,$c_1,$c_2,1,
2029                 $a_2,$a_3);             # mul_add_c2(a[2],b[3],c3,c1,c2);
2030         &add_c2($t_2,$t_1,$c_3,$c_1,$c_2,1,
2031                 $a_6,$a_0);             # mul_add_c2(a[6],b[0],c1,c2,c3);
2032 $code.=<<___;
2033         $ST     $c_3,5*$BNSZ($a0)
2034 ___
2035         &add_c2($t_2,$t_1,$c_1,$c_2,$c_3,0,
2036                 $a_5,$a_1);             # mul_add_c2(a[5],b[1],c1,c2,c3);
2037         &add_c2($t_2,$t_1,$c_1,$c_2,$c_3,1,
2038                 $a_4,$a_2);             # mul_add_c2(a[4],b[2],c1,c2,c3);
2039         &add_c2($t_2,$t_1,$c_1,$c_2,$c_3,1,
2040                 $a_3,$a_3);             # mul_add_c(a[3],b[3],c1,c2,c3);
2041 $code.=<<___;
2042         $ADDU   $c_1,$t_1
2043         sltu    $at,$c_1,$t_1
2044          $MULTU ($a_0,$a_7)             # mul_add_c2(a[0],b[7],c2,c3,c1);
2045         $ADDU   $t_2,$at
2046         $ADDU   $c_2,$t_2
2047         sltu    $at,$c_2,$t_2
2048         $ADDU   $c_3,$at
2049         $ST     $c_1,6*$BNSZ($a0)
2050         mflo    ($t_1,$a_0,$a_7)
2051         mfhi    ($t_2,$a_0,$a_7)
2052 ___
2053         &add_c2($t_2,$t_1,$c_2,$c_3,$c_1,0,
2054                 $a_1,$a_6);             # mul_add_c2(a[1],b[6],c2,c3,c1);
2055         &add_c2($t_2,$t_1,$c_2,$c_3,$c_1,1,
2056                 $a_2,$a_5);             # mul_add_c2(a[2],b[5],c2,c3,c1);
2057         &add_c2($t_2,$t_1,$c_2,$c_3,$c_1,1,
2058                 $a_3,$a_4);             # mul_add_c2(a[3],b[4],c2,c3,c1);
2059         &add_c2($t_2,$t_1,$c_2,$c_3,$c_1,1,
2060                 $a_7,$a_1);             # mul_add_c2(a[7],b[1],c3,c1,c2);
2061 $code.=<<___;
2062         $ST     $c_2,7*$BNSZ($a0)
2063 ___
2064         &add_c2($t_2,$t_1,$c_3,$c_1,$c_2,0,
2065                 $a_6,$a_2);             # mul_add_c2(a[6],b[2],c3,c1,c2);
2066         &add_c2($t_2,$t_1,$c_3,$c_1,$c_2,1,
2067                 $a_5,$a_3);             # mul_add_c2(a[5],b[3],c3,c1,c2);
2068         &add_c2($t_2,$t_1,$c_3,$c_1,$c_2,1,
2069                 $a_4,$a_4);             # mul_add_c(a[4],b[4],c3,c1,c2);
2070 $code.=<<___;
2071         $ADDU   $c_3,$t_1
2072         sltu    $at,$c_3,$t_1
2073          $MULTU ($a_2,$a_7)             # mul_add_c2(a[2],b[7],c1,c2,c3);
2074         $ADDU   $t_2,$at
2075         $ADDU   $c_1,$t_2
2076         sltu    $at,$c_1,$t_2
2077         $ADDU   $c_2,$at
2078         $ST     $c_3,8*$BNSZ($a0)
2079         mflo    ($t_1,$a_2,$a_7)
2080         mfhi    ($t_2,$a_2,$a_7)
2081 ___
2082         &add_c2($t_2,$t_1,$c_1,$c_2,$c_3,0,
2083                 $a_3,$a_6);             # mul_add_c2(a[3],b[6],c1,c2,c3);
2084         &add_c2($t_2,$t_1,$c_1,$c_2,$c_3,1,
2085                 $a_4,$a_5);             # mul_add_c2(a[4],b[5],c1,c2,c3);
2086         &add_c2($t_2,$t_1,$c_1,$c_2,$c_3,1,
2087                 $a_7,$a_3);             # mul_add_c2(a[7],b[3],c2,c3,c1);
2088 $code.=<<___;
2089         $ST     $c_1,9*$BNSZ($a0)
2090 ___
2091         &add_c2($t_2,$t_1,$c_2,$c_3,$c_1,0,
2092                 $a_6,$a_4);             # mul_add_c2(a[6],b[4],c2,c3,c1);
2093         &add_c2($t_2,$t_1,$c_2,$c_3,$c_1,1,
2094                 $a_5,$a_5);             # mul_add_c(a[5],b[5],c2,c3,c1);
2095 $code.=<<___;
2096         $ADDU   $c_2,$t_1
2097         sltu    $at,$c_2,$t_1
2098          $MULTU ($a_4,$a_7)             # mul_add_c2(a[4],b[7],c3,c1,c2);
2099         $ADDU   $t_2,$at
2100         $ADDU   $c_3,$t_2
2101         sltu    $at,$c_3,$t_2
2102         $ADDU   $c_1,$at
2103         $ST     $c_2,10*$BNSZ($a0)
2104         mflo    ($t_1,$a_4,$a_7)
2105         mfhi    ($t_2,$a_4,$a_7)
2106 ___
2107         &add_c2($t_2,$t_1,$c_3,$c_1,$c_2,0,
2108                 $a_5,$a_6);             # mul_add_c2(a[5],b[6],c3,c1,c2);
2109         &add_c2($t_2,$t_1,$c_3,$c_1,$c_2,1,
2110                 $a_7,$a_5);             # mul_add_c2(a[7],b[5],c1,c2,c3);
2111 $code.=<<___;
2112         $ST     $c_3,11*$BNSZ($a0)
2113 ___
2114         &add_c2($t_2,$t_1,$c_1,$c_2,$c_3,0,
2115                 $a_6,$a_6);             # mul_add_c(a[6],b[6],c1,c2,c3);
2116 $code.=<<___;
2117         $ADDU   $c_1,$t_1
2118         sltu    $at,$c_1,$t_1
2119          $MULTU ($a_6,$a_7)             # mul_add_c2(a[6],b[7],c2,c3,c1);
2120         $ADDU   $t_2,$at
2121         $ADDU   $c_2,$t_2
2122         sltu    $at,$c_2,$t_2
2123         $ADDU   $c_3,$at
2124         $ST     $c_1,12*$BNSZ($a0)
2125         mflo    ($t_1,$a_6,$a_7)
2126         mfhi    ($t_2,$a_6,$a_7)
2127 ___
2128         &add_c2($t_2,$t_1,$c_2,$c_3,$c_1,0,
2129                 $a_7,$a_7);             # mul_add_c(a[7],b[7],c3,c1,c2);
2130 $code.=<<___;
2131         $ST     $c_2,13*$BNSZ($a0)
2132
2133         $ADDU   $c_3,$t_1
2134         sltu    $at,$c_3,$t_1
2135         $ADDU   $t_2,$at
2136         $ADDU   $c_1,$t_2
2137         $ST     $c_3,14*$BNSZ($a0)
2138         $ST     $c_1,15*$BNSZ($a0)
2139
2140         .set    noreorder
2141 ___
2142 $code.=<<___ if ($flavour =~ /nubi/i);
2143         $REG_L  $t3,4*$SZREG($sp)
2144         $REG_L  $t2,3*$SZREG($sp)
2145         $REG_L  $t1,2*$SZREG($sp)
2146         $REG_L  $t0,1*$SZREG($sp)
2147         $REG_L  $gp,0*$SZREG($sp)
2148         $PTR_ADD $sp,6*$SZREG
2149 ___
2150 $code.=<<___;
2151         jr      $ra
2152         nop
2153 .end    bn_sqr_comba8
2154
2155 .align  5
2156 .globl  bn_sqr_comba4
2157 .ent    bn_sqr_comba4
2158 bn_sqr_comba4:
2159 ___
2160 $code.=<<___ if ($flavour =~ /nubi/i);
2161         .frame  $sp,6*$SZREG,$ra
2162         .mask   0x8000f008,-$SZREG
2163         .set    noreorder
2164         $PTR_SUB $sp,6*$SZREG
2165         $REG_S  $ra,5*$SZREG($sp)
2166         $REG_S  $t3,4*$SZREG($sp)
2167         $REG_S  $t2,3*$SZREG($sp)
2168         $REG_S  $t1,2*$SZREG($sp)
2169         $REG_S  $t0,1*$SZREG($sp)
2170         $REG_S  $gp,0*$SZREG($sp)
2171 ___
2172 $code.=<<___;
2173         .set    reorder
2174         $LD     $a_0,0($a1)
2175         $LD     $a_1,$BNSZ($a1)
2176         $MULTU  ($a_0,$a_0)             # mul_add_c(a[0],b[0],c1,c2,c3);
2177         $LD     $a_2,2*$BNSZ($a1)
2178         $LD     $a_3,3*$BNSZ($a1)
2179         mflo    ($c_1,$a_0,$a_0)
2180         mfhi    ($c_2,$a_0,$a_0)
2181         $ST     $c_1,0($a0)
2182
2183         $MULTU  ($a_0,$a_1)             # mul_add_c2(a[0],b[1],c2,c3,c1);
2184         mflo    ($t_1,$a_0,$a_1)
2185         mfhi    ($t_2,$a_0,$a_1)
2186         slt     $c_1,$t_2,$zero
2187         $SLL    $t_2,1
2188          $MULTU ($a_2,$a_0)             # mul_add_c2(a[2],b[0],c3,c1,c2);
2189         slt     $a2,$t_1,$zero
2190         $ADDU   $t_2,$a2
2191         $SLL    $t_1,1
2192         $ADDU   $c_2,$t_1
2193         sltu    $at,$c_2,$t_1
2194         $ADDU   $c_3,$t_2,$at
2195         $ST     $c_2,$BNSZ($a0)
2196         mflo    ($t_1,$a_2,$a_0)
2197         mfhi    ($t_2,$a_2,$a_0)
2198 ___
2199         &add_c2($t_2,$t_1,$c_3,$c_1,$c_2,0,
2200                 $a_1,$a_1);             # mul_add_c(a[1],b[1],c3,c1,c2);
2201 $code.=<<___;
2202         $ADDU   $c_3,$t_1
2203         sltu    $at,$c_3,$t_1
2204          $MULTU ($a_0,$a_3)             # mul_add_c2(a[0],b[3],c1,c2,c3);
2205         $ADDU   $t_2,$at
2206         $ADDU   $c_1,$t_2
2207         sltu    $at,$c_1,$t_2
2208         $ADDU   $c_2,$at
2209         $ST     $c_3,2*$BNSZ($a0)
2210         mflo    ($t_1,$a_0,$a_3)
2211         mfhi    ($t_2,$a_0,$a_3)
2212 ___
2213         &add_c2($t_2,$t_1,$c_1,$c_2,$c_3,0,
2214                 $a_1,$a_2);             # mul_add_c2(a2[1],b[2],c1,c2,c3);
2215         &add_c2($t_2,$t_1,$c_1,$c_2,$c_3,1,
2216                 $a_3,$a_1);             # mul_add_c2(a[3],b[1],c2,c3,c1);
2217 $code.=<<___;
2218         $ST     $c_1,3*$BNSZ($a0)
2219 ___
2220         &add_c2($t_2,$t_1,$c_2,$c_3,$c_1,0,
2221                 $a_2,$a_2);             # mul_add_c(a[2],b[2],c2,c3,c1);
2222 $code.=<<___;
2223         $ADDU   $c_2,$t_1
2224         sltu    $at,$c_2,$t_1
2225          $MULTU ($a_2,$a_3)             # mul_add_c2(a[2],b[3],c3,c1,c2);
2226         $ADDU   $t_2,$at
2227         $ADDU   $c_3,$t_2
2228         sltu    $at,$c_3,$t_2
2229         $ADDU   $c_1,$at
2230         $ST     $c_2,4*$BNSZ($a0)
2231         mflo    ($t_1,$a_2,$a_3)
2232         mfhi    ($t_2,$a_2,$a_3)
2233 ___
2234         &add_c2($t_2,$t_1,$c_3,$c_1,$c_2,0,
2235                 $a_3,$a_3);             # mul_add_c(a[3],b[3],c1,c2,c3);
2236 $code.=<<___;
2237         $ST     $c_3,5*$BNSZ($a0)
2238
2239         $ADDU   $c_1,$t_1
2240         sltu    $at,$c_1,$t_1
2241         $ADDU   $t_2,$at
2242         $ADDU   $c_2,$t_2
2243         $ST     $c_1,6*$BNSZ($a0)
2244         $ST     $c_2,7*$BNSZ($a0)
2245
2246         .set    noreorder
2247 ___
2248 $code.=<<___ if ($flavour =~ /nubi/i);
2249         $REG_L  $t3,4*$SZREG($sp)
2250         $REG_L  $t2,3*$SZREG($sp)
2251         $REG_L  $t1,2*$SZREG($sp)
2252         $REG_L  $t0,1*$SZREG($sp)
2253         $REG_L  $gp,0*$SZREG($sp)
2254         $PTR_ADD $sp,6*$SZREG
2255 ___
2256 $code.=<<___;
2257         jr      $ra
2258         nop
2259 .end    bn_sqr_comba4
2260 ___
2261 print $code;
2262 close STDOUT;