1#!/usr/bin/env perl 2# 3# Implemented as a Perl wrapper as we want to support several different 4# architectures with single file. We pick up the target based on the 5# file name we are asked to generate. 6# 7# It should be noted though that this perl code is nothing like 8# <openssl>/crypto/perlasm/x86*. In this case perl is used pretty much 9# as pre-processor to cover for platform differences in name decoration, 10# linker tables, 32-/64-bit instruction sets... 11# 12# As you might know there're several PowerPC ABI in use. Most notably 13# Linux and AIX use different 32-bit ABIs. Good news are that these ABIs 14# are similar enough to implement leaf(!) functions, which would be ABI 15# neutral. And that's what you find here: ABI neutral leaf functions. 16# In case you wonder what that is... 17# 18# AIX performance 19# 20# MEASUREMENTS WITH cc ON a 200 MhZ PowerPC 604e. 21# 22# The following is the performance of 32-bit compiler 23# generated code: 24# 25# OpenSSL 0.9.6c 21 dec 2001 26# built on: Tue Jun 11 11:06:51 EDT 2002 27# options:bn(64,32) ... 28#compiler: cc -DTHREADS -DAIX -DB_ENDIAN -DBN_LLONG -O3 29# sign verify sign/s verify/s 30#rsa 512 bits 0.0098s 0.0009s 102.0 1170.6 31#rsa 1024 bits 0.0507s 0.0026s 19.7 387.5 32#rsa 2048 bits 0.3036s 0.0085s 3.3 117.1 33#rsa 4096 bits 2.0040s 0.0299s 0.5 33.4 34#dsa 512 bits 0.0087s 0.0106s 114.3 94.5 35#dsa 1024 bits 0.0256s 0.0313s 39.0 32.0 36# 37# Same bechmark with this assembler code: 38# 39#rsa 512 bits 0.0056s 0.0005s 178.6 2049.2 40#rsa 1024 bits 0.0283s 0.0015s 35.3 674.1 41#rsa 2048 bits 0.1744s 0.0050s 5.7 201.2 42#rsa 4096 bits 1.1644s 0.0179s 0.9 55.7 43#dsa 512 bits 0.0052s 0.0062s 191.6 162.0 44#dsa 1024 bits 0.0149s 0.0180s 67.0 55.5 45# 46# Number of operations increases by at almost 75% 47# 48# Here are performance numbers for 64-bit compiler 49# generated code: 50# 51# OpenSSL 0.9.6g [engine] 9 Aug 2002 52# built on: Fri Apr 18 16:59:20 EDT 2003 53# options:bn(64,64) ... 54# compiler: cc -DTHREADS -D_REENTRANT -q64 -DB_ENDIAN -O3 55# sign verify sign/s verify/s 56#rsa 512 bits 0.0028s 0.0003s 357.1 3844.4 57#rsa 1024 bits 0.0148s 0.0008s 67.5 1239.7 58#rsa 2048 bits 0.0963s 0.0028s 10.4 353.0 59#rsa 4096 bits 0.6538s 0.0102s 1.5 98.1 60#dsa 512 bits 0.0026s 0.0032s 382.5 313.7 61#dsa 1024 bits 0.0081s 0.0099s 122.8 100.6 62# 63# Same benchmark with this assembler code: 64# 65#rsa 512 bits 0.0020s 0.0002s 510.4 6273.7 66#rsa 1024 bits 0.0088s 0.0005s 114.1 2128.3 67#rsa 2048 bits 0.0540s 0.0016s 18.5 622.5 68#rsa 4096 bits 0.3700s 0.0058s 2.7 171.0 69#dsa 512 bits 0.0016s 0.0020s 610.7 507.1 70#dsa 1024 bits 0.0047s 0.0058s 212.5 173.2 71# 72# Again, performance increases by at about 75% 73# 74# Mac OS X, Apple G5 1.8GHz (Note this is 32 bit code) 75# OpenSSL 0.9.7c 30 Sep 2003 76# 77# Original code. 78# 79#rsa 512 bits 0.0011s 0.0001s 906.1 11012.5 80#rsa 1024 bits 0.0060s 0.0003s 166.6 3363.1 81#rsa 2048 bits 0.0370s 0.0010s 27.1 982.4 82#rsa 4096 bits 0.2426s 0.0036s 4.1 280.4 83#dsa 512 bits 0.0010s 0.0012s 1038.1 841.5 84#dsa 1024 bits 0.0030s 0.0037s 329.6 269.7 85#dsa 2048 bits 0.0101s 0.0127s 98.9 78.6 86# 87# Same benchmark with this assembler code: 88# 89#rsa 512 bits 0.0007s 0.0001s 1416.2 16645.9 90#rsa 1024 bits 0.0036s 0.0002s 274.4 5380.6 91#rsa 2048 bits 0.0222s 0.0006s 45.1 1589.5 92#rsa 4096 bits 0.1469s 0.0022s 6.8 449.6 93#dsa 512 bits 0.0006s 0.0007s 1664.2 1376.2 94#dsa 1024 bits 0.0018s 0.0023s 545.0 442.2 95#dsa 2048 bits 0.0061s 0.0075s 163.5 132.8 96# 97# Performance increase of ~60% 98# 99# If you have comments or suggestions to improve code send 100# me a note at schari@us.ibm.com 101# 102 103$opf = shift; 104 105if ($opf =~ /32\.s/) { 106 $BITS= 32; 107 $BNSZ= $BITS/8; 108 $ISA= "\"ppc\""; 109 110 $LD= "lwz"; # load 111 $LDU= "lwzu"; # load and update 112 $ST= "stw"; # store 113 $STU= "stwu"; # store and update 114 $UMULL= "mullw"; # unsigned multiply low 115 $UMULH= "mulhwu"; # unsigned multiply high 116 $UDIV= "divwu"; # unsigned divide 117 $UCMPI= "cmplwi"; # unsigned compare with immediate 118 $UCMP= "cmplw"; # unsigned compare 119 $CNTLZ= "cntlzw"; # count leading zeros 120 $SHL= "slw"; # shift left 121 $SHR= "srw"; # unsigned shift right 122 $SHRI= "srwi"; # unsigned shift right by immediate 123 $SHLI= "slwi"; # shift left by immediate 124 $CLRU= "clrlwi"; # clear upper bits 125 $INSR= "insrwi"; # insert right 126 $ROTL= "rotlwi"; # rotate left by immediate 127 $TR= "tw"; # conditional trap 128} elsif ($opf =~ /64\.s/) { 129 $BITS= 64; 130 $BNSZ= $BITS/8; 131 $ISA= "\"ppc64\""; 132 133 # same as above, but 64-bit mnemonics... 134 $LD= "ld"; # load 135 $LDU= "ldu"; # load and update 136 $ST= "std"; # store 137 $STU= "stdu"; # store and update 138 $UMULL= "mulld"; # unsigned multiply low 139 $UMULH= "mulhdu"; # unsigned multiply high 140 $UDIV= "divdu"; # unsigned divide 141 $UCMPI= "cmpldi"; # unsigned compare with immediate 142 $UCMP= "cmpld"; # unsigned compare 143 $CNTLZ= "cntlzd"; # count leading zeros 144 $SHL= "sld"; # shift left 145 $SHR= "srd"; # unsigned shift right 146 $SHRI= "srdi"; # unsigned shift right by immediate 147 $SHLI= "sldi"; # shift left by immediate 148 $CLRU= "clrldi"; # clear upper bits 149 $INSR= "insrdi"; # insert right 150 $ROTL= "rotldi"; # rotate left by immediate 151 $TR= "td"; # conditional trap 152} else { die "nonsense $opf"; } 153 154( defined shift || open STDOUT,">$opf" ) || die "can't open $opf: $!"; 155 156# function entry points from the AIX code 157# 158# There are other, more elegant, ways to handle this. We (IBM) chose 159# this approach as it plays well with scripts we run to 'namespace' 160# OpenSSL .i.e. we add a prefix to all the public symbols so we can 161# co-exist in the same process with other implementations of OpenSSL. 162# 'cleverer' ways of doing these substitutions tend to hide data we 163# need to be obvious. 164# 165my @items = ("bn_sqr_comba4", 166 "bn_sqr_comba8", 167 "bn_mul_comba4", 168 "bn_mul_comba8", 169 "bn_sub_words", 170 "bn_add_words", 171 "bn_div_words", 172 "bn_sqr_words", 173 "bn_mul_words", 174 "bn_mul_add_words"); 175 176if ($opf =~ /linux/) { do_linux(); } 177elsif ($opf =~ /aix/) { do_aix(); } 178elsif ($opf =~ /osx/) { do_osx(); } 179else { do_bsd(); } 180 181sub do_linux { 182 $d=&data(); 183 184 if ($BITS==64) { 185 foreach $t (@items) { 186 $d =~ s/\.$t:/\ 187\t.section\t".opd","aw"\ 188\t.align\t3\ 189\t.globl\t$t\ 190$t:\ 191\t.quad\t.$t,.TOC.\@tocbase,0\ 192\t.size\t$t,24\ 193\t.previous\n\ 194\t.type\t.$t,\@function\ 195\t.globl\t.$t\ 196.$t:/g; 197 } 198 } 199 else { 200 foreach $t (@items) { 201 $d=~s/\.$t/$t/g; 202 } 203 } 204 # hide internal labels to avoid pollution of name table... 205 $d=~s/Lppcasm_/.Lppcasm_/gm; 206 print $d; 207} 208 209sub do_aix { 210 # AIX assembler is smart enough to please the linker without 211 # making us do something special... 212 print &data(); 213} 214 215# MacOSX 32 bit 216sub do_osx { 217 $d=&data(); 218 # Change the bn symbol prefix from '.' to '_' 219 foreach $t (@items) { 220 $d=~s/\.$t/_$t/g; 221 } 222 # Change .machine to something OS X asm will accept 223 $d=~s/\.machine.*/.text/g; 224 $d=~s/\#/;/g; # change comment from '#' to ';' 225 print $d; 226} 227 228# BSD (Untested) 229sub do_bsd { 230 $d=&data(); 231 foreach $t (@items) { 232 $d=~s/\.$t/_$t/g; 233 } 234 print $d; 235} 236 237sub data { 238 local($data)=<<EOF; 239#-------------------------------------------------------------------- 240# 241# 242# 243# 244# File: ppc32.s 245# 246# Created by: Suresh Chari 247# IBM Thomas J. Watson Research Library 248# Hawthorne, NY 249# 250# 251# Description: Optimized assembly routines for OpenSSL crypto 252# on the 32 bitPowerPC platform. 253# 254# 255# Version History 256# 257# 2. Fixed bn_add,bn_sub and bn_div_words, added comments, 258# cleaned up code. Also made a single version which can 259# be used for both the AIX and Linux compilers. See NOTE 260# below. 261# 12/05/03 Suresh Chari 262# (with lots of help from) Andy Polyakov 263## 264# 1. Initial version 10/20/02 Suresh Chari 265# 266# 267# The following file works for the xlc,cc 268# and gcc compilers. 269# 270# NOTE: To get the file to link correctly with the gcc compiler 271# you have to change the names of the routines and remove 272# the first .(dot) character. This should automatically 273# be done in the build process. 274# 275# Hand optimized assembly code for the following routines 276# 277# bn_sqr_comba4 278# bn_sqr_comba8 279# bn_mul_comba4 280# bn_mul_comba8 281# bn_sub_words 282# bn_add_words 283# bn_div_words 284# bn_sqr_words 285# bn_mul_words 286# bn_mul_add_words 287# 288# NOTE: It is possible to optimize this code more for 289# specific PowerPC or Power architectures. On the Northstar 290# architecture the optimizations in this file do 291# NOT provide much improvement. 292# 293# If you have comments or suggestions to improve code send 294# me a note at schari\@us.ibm.com 295# 296#-------------------------------------------------------------------------- 297# 298# Defines to be used in the assembly code. 299# 300.set r0,0 # we use it as storage for value of 0 301.set SP,1 # preserved 302.set RTOC,2 # preserved 303.set r3,3 # 1st argument/return value 304.set r4,4 # 2nd argument/volatile register 305.set r5,5 # 3rd argument/volatile register 306.set r6,6 # ... 307.set r7,7 308.set r8,8 309.set r9,9 310.set r10,10 311.set r11,11 312.set r12,12 313.set r13,13 # not used, nor any other "below" it... 314 315.set BO_IF_NOT,4 316.set BO_IF,12 317.set BO_dCTR_NZERO,16 318.set BO_dCTR_ZERO,18 319.set BO_ALWAYS,20 320.set CR0_LT,0; 321.set CR0_GT,1; 322.set CR0_EQ,2 323.set CR1_FX,4; 324.set CR1_FEX,5; 325.set CR1_VX,6 326.set LR,8 327 328# Declare function names to be global 329# NOTE: For gcc these names MUST be changed to remove 330# the first . i.e. for example change ".bn_sqr_comba4" 331# to "bn_sqr_comba4". This should be automatically done 332# in the build. 333 334 .globl .bn_sqr_comba4 335 .globl .bn_sqr_comba8 336 .globl .bn_mul_comba4 337 .globl .bn_mul_comba8 338 .globl .bn_sub_words 339 .globl .bn_add_words 340 .globl .bn_div_words 341 .globl .bn_sqr_words 342 .globl .bn_mul_words 343 .globl .bn_mul_add_words 344 345# .text section 346 347 .machine $ISA 348 349# 350# NOTE: The following label name should be changed to 351# "bn_sqr_comba4" i.e. remove the first dot 352# for the gcc compiler. This should be automatically 353# done in the build 354# 355 356.align 4 357.bn_sqr_comba4: 358# 359# Optimized version of bn_sqr_comba4. 360# 361# void bn_sqr_comba4(BN_ULONG *r, BN_ULONG *a) 362# r3 contains r 363# r4 contains a 364# 365# Freely use registers r5,r6,r7,r8,r9,r10,r11 as follows: 366# 367# r5,r6 are the two BN_ULONGs being multiplied. 368# r7,r8 are the results of the 32x32 giving 64 bit multiply. 369# r9,r10, r11 are the equivalents of c1,c2, c3. 370# Here's the assembly 371# 372# 373 xor r0,r0,r0 # set r0 = 0. Used in the addze 374 # instructions below 375 376 #sqr_add_c(a,0,c1,c2,c3) 377 $LD r5,`0*$BNSZ`(r4) 378 $UMULL r9,r5,r5 379 $UMULH r10,r5,r5 #in first iteration. No need 380 #to add since c1=c2=c3=0. 381 # Note c3(r11) is NOT set to 0 382 # but will be. 383 384 $ST r9,`0*$BNSZ`(r3) # r[0]=c1; 385 # sqr_add_c2(a,1,0,c2,c3,c1); 386 $LD r6,`1*$BNSZ`(r4) 387 $UMULL r7,r5,r6 388 $UMULH r8,r5,r6 389 390 addc r7,r7,r7 # compute (r7,r8)=2*(r7,r8) 391 adde r8,r8,r8 392 addze r9,r0 # catch carry if any. 393 # r9= r0(=0) and carry 394 395 addc r10,r7,r10 # now add to temp result. 396 addze r11,r8 # r8 added to r11 which is 0 397 addze r9,r9 398 399 $ST r10,`1*$BNSZ`(r3) #r[1]=c2; 400 #sqr_add_c(a,1,c3,c1,c2) 401 $UMULL r7,r6,r6 402 $UMULH r8,r6,r6 403 addc r11,r7,r11 404 adde r9,r8,r9 405 addze r10,r0 406 #sqr_add_c2(a,2,0,c3,c1,c2) 407 $LD r6,`2*$BNSZ`(r4) 408 $UMULL r7,r5,r6 409 $UMULH r8,r5,r6 410 411 addc r7,r7,r7 412 adde r8,r8,r8 413 addze r10,r10 414 415 addc r11,r7,r11 416 adde r9,r8,r9 417 addze r10,r10 418 $ST r11,`2*$BNSZ`(r3) #r[2]=c3 419 #sqr_add_c2(a,3,0,c1,c2,c3); 420 $LD r6,`3*$BNSZ`(r4) 421 $UMULL r7,r5,r6 422 $UMULH r8,r5,r6 423 addc r7,r7,r7 424 adde r8,r8,r8 425 addze r11,r0 426 427 addc r9,r7,r9 428 adde r10,r8,r10 429 addze r11,r11 430 #sqr_add_c2(a,2,1,c1,c2,c3); 431 $LD r5,`1*$BNSZ`(r4) 432 $LD r6,`2*$BNSZ`(r4) 433 $UMULL r7,r5,r6 434 $UMULH r8,r5,r6 435 436 addc r7,r7,r7 437 adde r8,r8,r8 438 addze r11,r11 439 addc r9,r7,r9 440 adde r10,r8,r10 441 addze r11,r11 442 $ST r9,`3*$BNSZ`(r3) #r[3]=c1 443 #sqr_add_c(a,2,c2,c3,c1); 444 $UMULL r7,r6,r6 445 $UMULH r8,r6,r6 446 addc r10,r7,r10 447 adde r11,r8,r11 448 addze r9,r0 449 #sqr_add_c2(a,3,1,c2,c3,c1); 450 $LD r6,`3*$BNSZ`(r4) 451 $UMULL r7,r5,r6 452 $UMULH r8,r5,r6 453 addc r7,r7,r7 454 adde r8,r8,r8 455 addze r9,r9 456 457 addc r10,r7,r10 458 adde r11,r8,r11 459 addze r9,r9 460 $ST r10,`4*$BNSZ`(r3) #r[4]=c2 461 #sqr_add_c2(a,3,2,c3,c1,c2); 462 $LD r5,`2*$BNSZ`(r4) 463 $UMULL r7,r5,r6 464 $UMULH r8,r5,r6 465 addc r7,r7,r7 466 adde r8,r8,r8 467 addze r10,r0 468 469 addc r11,r7,r11 470 adde r9,r8,r9 471 addze r10,r10 472 $ST r11,`5*$BNSZ`(r3) #r[5] = c3 473 #sqr_add_c(a,3,c1,c2,c3); 474 $UMULL r7,r6,r6 475 $UMULH r8,r6,r6 476 addc r9,r7,r9 477 adde r10,r8,r10 478 479 $ST r9,`6*$BNSZ`(r3) #r[6]=c1 480 $ST r10,`7*$BNSZ`(r3) #r[7]=c2 481 bclr BO_ALWAYS,CR0_LT 482 .long 0x00000000 483 484# 485# NOTE: The following label name should be changed to 486# "bn_sqr_comba8" i.e. remove the first dot 487# for the gcc compiler. This should be automatically 488# done in the build 489# 490 491.align 4 492.bn_sqr_comba8: 493# 494# This is an optimized version of the bn_sqr_comba8 routine. 495# Tightly uses the adde instruction 496# 497# 498# void bn_sqr_comba8(BN_ULONG *r, BN_ULONG *a) 499# r3 contains r 500# r4 contains a 501# 502# Freely use registers r5,r6,r7,r8,r9,r10,r11 as follows: 503# 504# r5,r6 are the two BN_ULONGs being multiplied. 505# r7,r8 are the results of the 32x32 giving 64 bit multiply. 506# r9,r10, r11 are the equivalents of c1,c2, c3. 507# 508# Possible optimization of loading all 8 longs of a into registers 509# doesnt provide any speedup 510# 511 512 xor r0,r0,r0 #set r0 = 0.Used in addze 513 #instructions below. 514 515 #sqr_add_c(a,0,c1,c2,c3); 516 $LD r5,`0*$BNSZ`(r4) 517 $UMULL r9,r5,r5 #1st iteration: no carries. 518 $UMULH r10,r5,r5 519 $ST r9,`0*$BNSZ`(r3) # r[0]=c1; 520 #sqr_add_c2(a,1,0,c2,c3,c1); 521 $LD r6,`1*$BNSZ`(r4) 522 $UMULL r7,r5,r6 523 $UMULH r8,r5,r6 524 525 addc r10,r7,r10 #add the two register number 526 adde r11,r8,r0 # (r8,r7) to the three register 527 addze r9,r0 # number (r9,r11,r10).NOTE:r0=0 528 529 addc r10,r7,r10 #add the two register number 530 adde r11,r8,r11 # (r8,r7) to the three register 531 addze r9,r9 # number (r9,r11,r10). 532 533 $ST r10,`1*$BNSZ`(r3) # r[1]=c2 534 535 #sqr_add_c(a,1,c3,c1,c2); 536 $UMULL r7,r6,r6 537 $UMULH r8,r6,r6 538 addc r11,r7,r11 539 adde r9,r8,r9 540 addze r10,r0 541 #sqr_add_c2(a,2,0,c3,c1,c2); 542 $LD r6,`2*$BNSZ`(r4) 543 $UMULL r7,r5,r6 544 $UMULH r8,r5,r6 545 546 addc r11,r7,r11 547 adde r9,r8,r9 548 addze r10,r10 549 550 addc r11,r7,r11 551 adde r9,r8,r9 552 addze r10,r10 553 554 $ST r11,`2*$BNSZ`(r3) #r[2]=c3 555 #sqr_add_c2(a,3,0,c1,c2,c3); 556 $LD r6,`3*$BNSZ`(r4) #r6 = a[3]. r5 is already a[0]. 557 $UMULL r7,r5,r6 558 $UMULH r8,r5,r6 559 560 addc r9,r7,r9 561 adde r10,r8,r10 562 addze r11,r0 563 564 addc r9,r7,r9 565 adde r10,r8,r10 566 addze r11,r11 567 #sqr_add_c2(a,2,1,c1,c2,c3); 568 $LD r5,`1*$BNSZ`(r4) 569 $LD r6,`2*$BNSZ`(r4) 570 $UMULL r7,r5,r6 571 $UMULH r8,r5,r6 572 573 addc r9,r7,r9 574 adde r10,r8,r10 575 addze r11,r11 576 577 addc r9,r7,r9 578 adde r10,r8,r10 579 addze r11,r11 580 581 $ST r9,`3*$BNSZ`(r3) #r[3]=c1; 582 #sqr_add_c(a,2,c2,c3,c1); 583 $UMULL r7,r6,r6 584 $UMULH r8,r6,r6 585 586 addc r10,r7,r10 587 adde r11,r8,r11 588 addze r9,r0 589 #sqr_add_c2(a,3,1,c2,c3,c1); 590 $LD r6,`3*$BNSZ`(r4) 591 $UMULL r7,r5,r6 592 $UMULH r8,r5,r6 593 594 addc r10,r7,r10 595 adde r11,r8,r11 596 addze r9,r9 597 598 addc r10,r7,r10 599 adde r11,r8,r11 600 addze r9,r9 601 #sqr_add_c2(a,4,0,c2,c3,c1); 602 $LD r5,`0*$BNSZ`(r4) 603 $LD r6,`4*$BNSZ`(r4) 604 $UMULL r7,r5,r6 605 $UMULH r8,r5,r6 606 607 addc r10,r7,r10 608 adde r11,r8,r11 609 addze r9,r9 610 611 addc r10,r7,r10 612 adde r11,r8,r11 613 addze r9,r9 614 $ST r10,`4*$BNSZ`(r3) #r[4]=c2; 615 #sqr_add_c2(a,5,0,c3,c1,c2); 616 $LD r6,`5*$BNSZ`(r4) 617 $UMULL r7,r5,r6 618 $UMULH r8,r5,r6 619 620 addc r11,r7,r11 621 adde r9,r8,r9 622 addze r10,r0 623 624 addc r11,r7,r11 625 adde r9,r8,r9 626 addze r10,r10 627 #sqr_add_c2(a,4,1,c3,c1,c2); 628 $LD r5,`1*$BNSZ`(r4) 629 $LD r6,`4*$BNSZ`(r4) 630 $UMULL r7,r5,r6 631 $UMULH r8,r5,r6 632 633 addc r11,r7,r11 634 adde r9,r8,r9 635 addze r10,r10 636 637 addc r11,r7,r11 638 adde r9,r8,r9 639 addze r10,r10 640 #sqr_add_c2(a,3,2,c3,c1,c2); 641 $LD r5,`2*$BNSZ`(r4) 642 $LD r6,`3*$BNSZ`(r4) 643 $UMULL r7,r5,r6 644 $UMULH r8,r5,r6 645 646 addc r11,r7,r11 647 adde r9,r8,r9 648 addze r10,r10 649 650 addc r11,r7,r11 651 adde r9,r8,r9 652 addze r10,r10 653 $ST r11,`5*$BNSZ`(r3) #r[5]=c3; 654 #sqr_add_c(a,3,c1,c2,c3); 655 $UMULL r7,r6,r6 656 $UMULH r8,r6,r6 657 addc r9,r7,r9 658 adde r10,r8,r10 659 addze r11,r0 660 #sqr_add_c2(a,4,2,c1,c2,c3); 661 $LD r6,`4*$BNSZ`(r4) 662 $UMULL r7,r5,r6 663 $UMULH r8,r5,r6 664 665 addc r9,r7,r9 666 adde r10,r8,r10 667 addze r11,r11 668 669 addc r9,r7,r9 670 adde r10,r8,r10 671 addze r11,r11 672 #sqr_add_c2(a,5,1,c1,c2,c3); 673 $LD r5,`1*$BNSZ`(r4) 674 $LD r6,`5*$BNSZ`(r4) 675 $UMULL r7,r5,r6 676 $UMULH r8,r5,r6 677 678 addc r9,r7,r9 679 adde r10,r8,r10 680 addze r11,r11 681 682 addc r9,r7,r9 683 adde r10,r8,r10 684 addze r11,r11 685 #sqr_add_c2(a,6,0,c1,c2,c3); 686 $LD r5,`0*$BNSZ`(r4) 687 $LD r6,`6*$BNSZ`(r4) 688 $UMULL r7,r5,r6 689 $UMULH r8,r5,r6 690 addc r9,r7,r9 691 adde r10,r8,r10 692 addze r11,r11 693 addc r9,r7,r9 694 adde r10,r8,r10 695 addze r11,r11 696 $ST r9,`6*$BNSZ`(r3) #r[6]=c1; 697 #sqr_add_c2(a,7,0,c2,c3,c1); 698 $LD r6,`7*$BNSZ`(r4) 699 $UMULL r7,r5,r6 700 $UMULH r8,r5,r6 701 702 addc r10,r7,r10 703 adde r11,r8,r11 704 addze r9,r0 705 addc r10,r7,r10 706 adde r11,r8,r11 707 addze r9,r9 708 #sqr_add_c2(a,6,1,c2,c3,c1); 709 $LD r5,`1*$BNSZ`(r4) 710 $LD r6,`6*$BNSZ`(r4) 711 $UMULL r7,r5,r6 712 $UMULH r8,r5,r6 713 714 addc r10,r7,r10 715 adde r11,r8,r11 716 addze r9,r9 717 addc r10,r7,r10 718 adde r11,r8,r11 719 addze r9,r9 720 #sqr_add_c2(a,5,2,c2,c3,c1); 721 $LD r5,`2*$BNSZ`(r4) 722 $LD r6,`5*$BNSZ`(r4) 723 $UMULL r7,r5,r6 724 $UMULH r8,r5,r6 725 addc r10,r7,r10 726 adde r11,r8,r11 727 addze r9,r9 728 addc r10,r7,r10 729 adde r11,r8,r11 730 addze r9,r9 731 #sqr_add_c2(a,4,3,c2,c3,c1); 732 $LD r5,`3*$BNSZ`(r4) 733 $LD r6,`4*$BNSZ`(r4) 734 $UMULL r7,r5,r6 735 $UMULH r8,r5,r6 736 737 addc r10,r7,r10 738 adde r11,r8,r11 739 addze r9,r9 740 addc r10,r7,r10 741 adde r11,r8,r11 742 addze r9,r9 743 $ST r10,`7*$BNSZ`(r3) #r[7]=c2; 744 #sqr_add_c(a,4,c3,c1,c2); 745 $UMULL r7,r6,r6 746 $UMULH r8,r6,r6 747 addc r11,r7,r11 748 adde r9,r8,r9 749 addze r10,r0 750 #sqr_add_c2(a,5,3,c3,c1,c2); 751 $LD r6,`5*$BNSZ`(r4) 752 $UMULL r7,r5,r6 753 $UMULH r8,r5,r6 754 addc r11,r7,r11 755 adde r9,r8,r9 756 addze r10,r10 757 addc r11,r7,r11 758 adde r9,r8,r9 759 addze r10,r10 760 #sqr_add_c2(a,6,2,c3,c1,c2); 761 $LD r5,`2*$BNSZ`(r4) 762 $LD r6,`6*$BNSZ`(r4) 763 $UMULL r7,r5,r6 764 $UMULH r8,r5,r6 765 addc r11,r7,r11 766 adde r9,r8,r9 767 addze r10,r10 768 769 addc r11,r7,r11 770 adde r9,r8,r9 771 addze r10,r10 772 #sqr_add_c2(a,7,1,c3,c1,c2); 773 $LD r5,`1*$BNSZ`(r4) 774 $LD r6,`7*$BNSZ`(r4) 775 $UMULL r7,r5,r6 776 $UMULH r8,r5,r6 777 addc r11,r7,r11 778 adde r9,r8,r9 779 addze r10,r10 780 addc r11,r7,r11 781 adde r9,r8,r9 782 addze r10,r10 783 $ST r11,`8*$BNSZ`(r3) #r[8]=c3; 784 #sqr_add_c2(a,7,2,c1,c2,c3); 785 $LD r5,`2*$BNSZ`(r4) 786 $UMULL r7,r5,r6 787 $UMULH r8,r5,r6 788 789 addc r9,r7,r9 790 adde r10,r8,r10 791 addze r11,r0 792 addc r9,r7,r9 793 adde r10,r8,r10 794 addze r11,r11 795 #sqr_add_c2(a,6,3,c1,c2,c3); 796 $LD r5,`3*$BNSZ`(r4) 797 $LD r6,`6*$BNSZ`(r4) 798 $UMULL r7,r5,r6 799 $UMULH r8,r5,r6 800 addc r9,r7,r9 801 adde r10,r8,r10 802 addze r11,r11 803 addc r9,r7,r9 804 adde r10,r8,r10 805 addze r11,r11 806 #sqr_add_c2(a,5,4,c1,c2,c3); 807 $LD r5,`4*$BNSZ`(r4) 808 $LD r6,`5*$BNSZ`(r4) 809 $UMULL r7,r5,r6 810 $UMULH r8,r5,r6 811 addc r9,r7,r9 812 adde r10,r8,r10 813 addze r11,r11 814 addc r9,r7,r9 815 adde r10,r8,r10 816 addze r11,r11 817 $ST r9,`9*$BNSZ`(r3) #r[9]=c1; 818 #sqr_add_c(a,5,c2,c3,c1); 819 $UMULL r7,r6,r6 820 $UMULH r8,r6,r6 821 addc r10,r7,r10 822 adde r11,r8,r11 823 addze r9,r0 824 #sqr_add_c2(a,6,4,c2,c3,c1); 825 $LD r6,`6*$BNSZ`(r4) 826 $UMULL r7,r5,r6 827 $UMULH r8,r5,r6 828 addc r10,r7,r10 829 adde r11,r8,r11 830 addze r9,r9 831 addc r10,r7,r10 832 adde r11,r8,r11 833 addze r9,r9 834 #sqr_add_c2(a,7,3,c2,c3,c1); 835 $LD r5,`3*$BNSZ`(r4) 836 $LD r6,`7*$BNSZ`(r4) 837 $UMULL r7,r5,r6 838 $UMULH r8,r5,r6 839 addc r10,r7,r10 840 adde r11,r8,r11 841 addze r9,r9 842 addc r10,r7,r10 843 adde r11,r8,r11 844 addze r9,r9 845 $ST r10,`10*$BNSZ`(r3) #r[10]=c2; 846 #sqr_add_c2(a,7,4,c3,c1,c2); 847 $LD r5,`4*$BNSZ`(r4) 848 $UMULL r7,r5,r6 849 $UMULH r8,r5,r6 850 addc r11,r7,r11 851 adde r9,r8,r9 852 addze r10,r0 853 addc r11,r7,r11 854 adde r9,r8,r9 855 addze r10,r10 856 #sqr_add_c2(a,6,5,c3,c1,c2); 857 $LD r5,`5*$BNSZ`(r4) 858 $LD r6,`6*$BNSZ`(r4) 859 $UMULL r7,r5,r6 860 $UMULH r8,r5,r6 861 addc r11,r7,r11 862 adde r9,r8,r9 863 addze r10,r10 864 addc r11,r7,r11 865 adde r9,r8,r9 866 addze r10,r10 867 $ST r11,`11*$BNSZ`(r3) #r[11]=c3; 868 #sqr_add_c(a,6,c1,c2,c3); 869 $UMULL r7,r6,r6 870 $UMULH r8,r6,r6 871 addc r9,r7,r9 872 adde r10,r8,r10 873 addze r11,r0 874 #sqr_add_c2(a,7,5,c1,c2,c3) 875 $LD r6,`7*$BNSZ`(r4) 876 $UMULL r7,r5,r6 877 $UMULH r8,r5,r6 878 addc r9,r7,r9 879 adde r10,r8,r10 880 addze r11,r11 881 addc r9,r7,r9 882 adde r10,r8,r10 883 addze r11,r11 884 $ST r9,`12*$BNSZ`(r3) #r[12]=c1; 885 886 #sqr_add_c2(a,7,6,c2,c3,c1) 887 $LD r5,`6*$BNSZ`(r4) 888 $UMULL r7,r5,r6 889 $UMULH r8,r5,r6 890 addc r10,r7,r10 891 adde r11,r8,r11 892 addze r9,r0 893 addc r10,r7,r10 894 adde r11,r8,r11 895 addze r9,r9 896 $ST r10,`13*$BNSZ`(r3) #r[13]=c2; 897 #sqr_add_c(a,7,c3,c1,c2); 898 $UMULL r7,r6,r6 899 $UMULH r8,r6,r6 900 addc r11,r7,r11 901 adde r9,r8,r9 902 $ST r11,`14*$BNSZ`(r3) #r[14]=c3; 903 $ST r9, `15*$BNSZ`(r3) #r[15]=c1; 904 905 906 bclr BO_ALWAYS,CR0_LT 907 908 .long 0x00000000 909 910# 911# NOTE: The following label name should be changed to 912# "bn_mul_comba4" i.e. remove the first dot 913# for the gcc compiler. This should be automatically 914# done in the build 915# 916 917.align 4 918.bn_mul_comba4: 919# 920# This is an optimized version of the bn_mul_comba4 routine. 921# 922# void bn_mul_comba4(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b) 923# r3 contains r 924# r4 contains a 925# r5 contains b 926# r6, r7 are the 2 BN_ULONGs being multiplied. 927# r8, r9 are the results of the 32x32 giving 64 multiply. 928# r10, r11, r12 are the equivalents of c1, c2, and c3. 929# 930 xor r0,r0,r0 #r0=0. Used in addze below. 931 #mul_add_c(a[0],b[0],c1,c2,c3); 932 $LD r6,`0*$BNSZ`(r4) 933 $LD r7,`0*$BNSZ`(r5) 934 $UMULL r10,r6,r7 935 $UMULH r11,r6,r7 936 $ST r10,`0*$BNSZ`(r3) #r[0]=c1 937 #mul_add_c(a[0],b[1],c2,c3,c1); 938 $LD r7,`1*$BNSZ`(r5) 939 $UMULL r8,r6,r7 940 $UMULH r9,r6,r7 941 addc r11,r8,r11 942 adde r12,r9,r0 943 addze r10,r0 944 #mul_add_c(a[1],b[0],c2,c3,c1); 945 $LD r6, `1*$BNSZ`(r4) 946 $LD r7, `0*$BNSZ`(r5) 947 $UMULL r8,r6,r7 948 $UMULH r9,r6,r7 949 addc r11,r8,r11 950 adde r12,r9,r12 951 addze r10,r10 952 $ST r11,`1*$BNSZ`(r3) #r[1]=c2 953 #mul_add_c(a[2],b[0],c3,c1,c2); 954 $LD r6,`2*$BNSZ`(r4) 955 $UMULL r8,r6,r7 956 $UMULH r9,r6,r7 957 addc r12,r8,r12 958 adde r10,r9,r10 959 addze r11,r0 960 #mul_add_c(a[1],b[1],c3,c1,c2); 961 $LD r6,`1*$BNSZ`(r4) 962 $LD r7,`1*$BNSZ`(r5) 963 $UMULL r8,r6,r7 964 $UMULH r9,r6,r7 965 addc r12,r8,r12 966 adde r10,r9,r10 967 addze r11,r11 968 #mul_add_c(a[0],b[2],c3,c1,c2); 969 $LD r6,`0*$BNSZ`(r4) 970 $LD r7,`2*$BNSZ`(r5) 971 $UMULL r8,r6,r7 972 $UMULH r9,r6,r7 973 addc r12,r8,r12 974 adde r10,r9,r10 975 addze r11,r11 976 $ST r12,`2*$BNSZ`(r3) #r[2]=c3 977 #mul_add_c(a[0],b[3],c1,c2,c3); 978 $LD r7,`3*$BNSZ`(r5) 979 $UMULL r8,r6,r7 980 $UMULH r9,r6,r7 981 addc r10,r8,r10 982 adde r11,r9,r11 983 addze r12,r0 984 #mul_add_c(a[1],b[2],c1,c2,c3); 985 $LD r6,`1*$BNSZ`(r4) 986 $LD r7,`2*$BNSZ`(r5) 987 $UMULL r8,r6,r7 988 $UMULH r9,r6,r7 989 addc r10,r8,r10 990 adde r11,r9,r11 991 addze r12,r12 992 #mul_add_c(a[2],b[1],c1,c2,c3); 993 $LD r6,`2*$BNSZ`(r4) 994 $LD r7,`1*$BNSZ`(r5) 995 $UMULL r8,r6,r7 996 $UMULH r9,r6,r7 997 addc r10,r8,r10 998 adde r11,r9,r11 999 addze r12,r12 1000 #mul_add_c(a[3],b[0],c1,c2,c3); 1001 $LD r6,`3*$BNSZ`(r4) 1002 $LD r7,`0*$BNSZ`(r5) 1003 $UMULL r8,r6,r7 1004 $UMULH r9,r6,r7 1005 addc r10,r8,r10 1006 adde r11,r9,r11 1007 addze r12,r12 1008 $ST r10,`3*$BNSZ`(r3) #r[3]=c1 1009 #mul_add_c(a[3],b[1],c2,c3,c1); 1010 $LD r7,`1*$BNSZ`(r5) 1011 $UMULL r8,r6,r7 1012 $UMULH r9,r6,r7 1013 addc r11,r8,r11 1014 adde r12,r9,r12 1015 addze r10,r0 1016 #mul_add_c(a[2],b[2],c2,c3,c1); 1017 $LD r6,`2*$BNSZ`(r4) 1018 $LD r7,`2*$BNSZ`(r5) 1019 $UMULL r8,r6,r7 1020 $UMULH r9,r6,r7 1021 addc r11,r8,r11 1022 adde r12,r9,r12 1023 addze r10,r10 1024 #mul_add_c(a[1],b[3],c2,c3,c1); 1025 $LD r6,`1*$BNSZ`(r4) 1026 $LD r7,`3*$BNSZ`(r5) 1027 $UMULL r8,r6,r7 1028 $UMULH r9,r6,r7 1029 addc r11,r8,r11 1030 adde r12,r9,r12 1031 addze r10,r10 1032 $ST r11,`4*$BNSZ`(r3) #r[4]=c2 1033 #mul_add_c(a[2],b[3],c3,c1,c2); 1034 $LD r6,`2*$BNSZ`(r4) 1035 $UMULL r8,r6,r7 1036 $UMULH r9,r6,r7 1037 addc r12,r8,r12 1038 adde r10,r9,r10 1039 addze r11,r0 1040 #mul_add_c(a[3],b[2],c3,c1,c2); 1041 $LD r6,`3*$BNSZ`(r4) 1042 $LD r7,`2*$BNSZ`(r4) 1043 $UMULL r8,r6,r7 1044 $UMULH r9,r6,r7 1045 addc r12,r8,r12 1046 adde r10,r9,r10 1047 addze r11,r11 1048 $ST r12,`5*$BNSZ`(r3) #r[5]=c3 1049 #mul_add_c(a[3],b[3],c1,c2,c3); 1050 $LD r7,`3*$BNSZ`(r5) 1051 $UMULL r8,r6,r7 1052 $UMULH r9,r6,r7 1053 addc r10,r8,r10 1054 adde r11,r9,r11 1055 1056 $ST r10,`6*$BNSZ`(r3) #r[6]=c1 1057 $ST r11,`7*$BNSZ`(r3) #r[7]=c2 1058 bclr BO_ALWAYS,CR0_LT 1059 .long 0x00000000 1060 1061# 1062# NOTE: The following label name should be changed to 1063# "bn_mul_comba8" i.e. remove the first dot 1064# for the gcc compiler. This should be automatically 1065# done in the build 1066# 1067 1068.align 4 1069.bn_mul_comba8: 1070# 1071# Optimized version of the bn_mul_comba8 routine. 1072# 1073# void bn_mul_comba8(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b) 1074# r3 contains r 1075# r4 contains a 1076# r5 contains b 1077# r6, r7 are the 2 BN_ULONGs being multiplied. 1078# r8, r9 are the results of the 32x32 giving 64 multiply. 1079# r10, r11, r12 are the equivalents of c1, c2, and c3. 1080# 1081 xor r0,r0,r0 #r0=0. Used in addze below. 1082 1083 #mul_add_c(a[0],b[0],c1,c2,c3); 1084 $LD r6,`0*$BNSZ`(r4) #a[0] 1085 $LD r7,`0*$BNSZ`(r5) #b[0] 1086 $UMULL r10,r6,r7 1087 $UMULH r11,r6,r7 1088 $ST r10,`0*$BNSZ`(r3) #r[0]=c1; 1089 #mul_add_c(a[0],b[1],c2,c3,c1); 1090 $LD r7,`1*$BNSZ`(r5) 1091 $UMULL r8,r6,r7 1092 $UMULH r9,r6,r7 1093 addc r11,r11,r8 1094 addze r12,r9 # since we didnt set r12 to zero before. 1095 addze r10,r0 1096 #mul_add_c(a[1],b[0],c2,c3,c1); 1097 $LD r6,`1*$BNSZ`(r4) 1098 $LD r7,`0*$BNSZ`(r5) 1099 $UMULL r8,r6,r7 1100 $UMULH r9,r6,r7 1101 addc r11,r11,r8 1102 adde r12,r12,r9 1103 addze r10,r10 1104 $ST r11,`1*$BNSZ`(r3) #r[1]=c2; 1105 #mul_add_c(a[2],b[0],c3,c1,c2); 1106 $LD r6,`2*$BNSZ`(r4) 1107 $UMULL r8,r6,r7 1108 $UMULH r9,r6,r7 1109 addc r12,r12,r8 1110 adde r10,r10,r9 1111 addze r11,r0 1112 #mul_add_c(a[1],b[1],c3,c1,c2); 1113 $LD r6,`1*$BNSZ`(r4) 1114 $LD r7,`1*$BNSZ`(r5) 1115 $UMULL r8,r6,r7 1116 $UMULH r9,r6,r7 1117 addc r12,r12,r8 1118 adde r10,r10,r9 1119 addze r11,r11 1120 #mul_add_c(a[0],b[2],c3,c1,c2); 1121 $LD r6,`0*$BNSZ`(r4) 1122 $LD r7,`2*$BNSZ`(r5) 1123 $UMULL r8,r6,r7 1124 $UMULH r9,r6,r7 1125 addc r12,r12,r8 1126 adde r10,r10,r9 1127 addze r11,r11 1128 $ST r12,`2*$BNSZ`(r3) #r[2]=c3; 1129 #mul_add_c(a[0],b[3],c1,c2,c3); 1130 $LD r7,`3*$BNSZ`(r5) 1131 $UMULL r8,r6,r7 1132 $UMULH r9,r6,r7 1133 addc r10,r10,r8 1134 adde r11,r11,r9 1135 addze r12,r0 1136 #mul_add_c(a[1],b[2],c1,c2,c3); 1137 $LD r6,`1*$BNSZ`(r4) 1138 $LD r7,`2*$BNSZ`(r5) 1139 $UMULL r8,r6,r7 1140 $UMULH r9,r6,r7 1141 addc r10,r10,r8 1142 adde r11,r11,r9 1143 addze r12,r12 1144 1145 #mul_add_c(a[2],b[1],c1,c2,c3); 1146 $LD r6,`2*$BNSZ`(r4) 1147 $LD r7,`1*$BNSZ`(r5) 1148 $UMULL r8,r6,r7 1149 $UMULH r9,r6,r7 1150 addc r10,r10,r8 1151 adde r11,r11,r9 1152 addze r12,r12 1153 #mul_add_c(a[3],b[0],c1,c2,c3); 1154 $LD r6,`3*$BNSZ`(r4) 1155 $LD r7,`0*$BNSZ`(r5) 1156 $UMULL r8,r6,r7 1157 $UMULH r9,r6,r7 1158 addc r10,r10,r8 1159 adde r11,r11,r9 1160 addze r12,r12 1161 $ST r10,`3*$BNSZ`(r3) #r[3]=c1; 1162 #mul_add_c(a[4],b[0],c2,c3,c1); 1163 $LD r6,`4*$BNSZ`(r4) 1164 $UMULL r8,r6,r7 1165 $UMULH r9,r6,r7 1166 addc r11,r11,r8 1167 adde r12,r12,r9 1168 addze r10,r0 1169 #mul_add_c(a[3],b[1],c2,c3,c1); 1170 $LD r6,`3*$BNSZ`(r4) 1171 $LD r7,`1*$BNSZ`(r5) 1172 $UMULL r8,r6,r7 1173 $UMULH r9,r6,r7 1174 addc r11,r11,r8 1175 adde r12,r12,r9 1176 addze r10,r10 1177 #mul_add_c(a[2],b[2],c2,c3,c1); 1178 $LD r6,`2*$BNSZ`(r4) 1179 $LD r7,`2*$BNSZ`(r5) 1180 $UMULL r8,r6,r7 1181 $UMULH r9,r6,r7 1182 addc r11,r11,r8 1183 adde r12,r12,r9 1184 addze r10,r10 1185 #mul_add_c(a[1],b[3],c2,c3,c1); 1186 $LD r6,`1*$BNSZ`(r4) 1187 $LD r7,`3*$BNSZ`(r5) 1188 $UMULL r8,r6,r7 1189 $UMULH r9,r6,r7 1190 addc r11,r11,r8 1191 adde r12,r12,r9 1192 addze r10,r10 1193 #mul_add_c(a[0],b[4],c2,c3,c1); 1194 $LD r6,`0*$BNSZ`(r4) 1195 $LD r7,`4*$BNSZ`(r5) 1196 $UMULL r8,r6,r7 1197 $UMULH r9,r6,r7 1198 addc r11,r11,r8 1199 adde r12,r12,r9 1200 addze r10,r10 1201 $ST r11,`4*$BNSZ`(r3) #r[4]=c2; 1202 #mul_add_c(a[0],b[5],c3,c1,c2); 1203 $LD r7,`5*$BNSZ`(r5) 1204 $UMULL r8,r6,r7 1205 $UMULH r9,r6,r7 1206 addc r12,r12,r8 1207 adde r10,r10,r9 1208 addze r11,r0 1209 #mul_add_c(a[1],b[4],c3,c1,c2); 1210 $LD r6,`1*$BNSZ`(r4) 1211 $LD r7,`4*$BNSZ`(r5) 1212 $UMULL r8,r6,r7 1213 $UMULH r9,r6,r7 1214 addc r12,r12,r8 1215 adde r10,r10,r9 1216 addze r11,r11 1217 #mul_add_c(a[2],b[3],c3,c1,c2); 1218 $LD r6,`2*$BNSZ`(r4) 1219 $LD r7,`3*$BNSZ`(r5) 1220 $UMULL r8,r6,r7 1221 $UMULH r9,r6,r7 1222 addc r12,r12,r8 1223 adde r10,r10,r9 1224 addze r11,r11 1225 #mul_add_c(a[3],b[2],c3,c1,c2); 1226 $LD r6,`3*$BNSZ`(r4) 1227 $LD r7,`2*$BNSZ`(r5) 1228 $UMULL r8,r6,r7 1229 $UMULH r9,r6,r7 1230 addc r12,r12,r8 1231 adde r10,r10,r9 1232 addze r11,r11 1233 #mul_add_c(a[4],b[1],c3,c1,c2); 1234 $LD r6,`4*$BNSZ`(r4) 1235 $LD r7,`1*$BNSZ`(r5) 1236 $UMULL r8,r6,r7 1237 $UMULH r9,r6,r7 1238 addc r12,r12,r8 1239 adde r10,r10,r9 1240 addze r11,r11 1241 #mul_add_c(a[5],b[0],c3,c1,c2); 1242 $LD r6,`5*$BNSZ`(r4) 1243 $LD r7,`0*$BNSZ`(r5) 1244 $UMULL r8,r6,r7 1245 $UMULH r9,r6,r7 1246 addc r12,r12,r8 1247 adde r10,r10,r9 1248 addze r11,r11 1249 $ST r12,`5*$BNSZ`(r3) #r[5]=c3; 1250 #mul_add_c(a[6],b[0],c1,c2,c3); 1251 $LD r6,`6*$BNSZ`(r4) 1252 $UMULL r8,r6,r7 1253 $UMULH r9,r6,r7 1254 addc r10,r10,r8 1255 adde r11,r11,r9 1256 addze r12,r0 1257 #mul_add_c(a[5],b[1],c1,c2,c3); 1258 $LD r6,`5*$BNSZ`(r4) 1259 $LD r7,`1*$BNSZ`(r5) 1260 $UMULL r8,r6,r7 1261 $UMULH r9,r6,r7 1262 addc r10,r10,r8 1263 adde r11,r11,r9 1264 addze r12,r12 1265 #mul_add_c(a[4],b[2],c1,c2,c3); 1266 $LD r6,`4*$BNSZ`(r4) 1267 $LD r7,`2*$BNSZ`(r5) 1268 $UMULL r8,r6,r7 1269 $UMULH r9,r6,r7 1270 addc r10,r10,r8 1271 adde r11,r11,r9 1272 addze r12,r12 1273 #mul_add_c(a[3],b[3],c1,c2,c3); 1274 $LD r6,`3*$BNSZ`(r4) 1275 $LD r7,`3*$BNSZ`(r5) 1276 $UMULL r8,r6,r7 1277 $UMULH r9,r6,r7 1278 addc r10,r10,r8 1279 adde r11,r11,r9 1280 addze r12,r12 1281 #mul_add_c(a[2],b[4],c1,c2,c3); 1282 $LD r6,`2*$BNSZ`(r4) 1283 $LD r7,`4*$BNSZ`(r5) 1284 $UMULL r8,r6,r7 1285 $UMULH r9,r6,r7 1286 addc r10,r10,r8 1287 adde r11,r11,r9 1288 addze r12,r12 1289 #mul_add_c(a[1],b[5],c1,c2,c3); 1290 $LD r6,`1*$BNSZ`(r4) 1291 $LD r7,`5*$BNSZ`(r5) 1292 $UMULL r8,r6,r7 1293 $UMULH r9,r6,r7 1294 addc r10,r10,r8 1295 adde r11,r11,r9 1296 addze r12,r12 1297 #mul_add_c(a[0],b[6],c1,c2,c3); 1298 $LD r6,`0*$BNSZ`(r4) 1299 $LD r7,`6*$BNSZ`(r5) 1300 $UMULL r8,r6,r7 1301 $UMULH r9,r6,r7 1302 addc r10,r10,r8 1303 adde r11,r11,r9 1304 addze r12,r12 1305 $ST r10,`6*$BNSZ`(r3) #r[6]=c1; 1306 #mul_add_c(a[0],b[7],c2,c3,c1); 1307 $LD r7,`7*$BNSZ`(r5) 1308 $UMULL r8,r6,r7 1309 $UMULH r9,r6,r7 1310 addc r11,r11,r8 1311 adde r12,r12,r9 1312 addze r10,r0 1313 #mul_add_c(a[1],b[6],c2,c3,c1); 1314 $LD r6,`1*$BNSZ`(r4) 1315 $LD r7,`6*$BNSZ`(r5) 1316 $UMULL r8,r6,r7 1317 $UMULH r9,r6,r7 1318 addc r11,r11,r8 1319 adde r12,r12,r9 1320 addze r10,r10 1321 #mul_add_c(a[2],b[5],c2,c3,c1); 1322 $LD r6,`2*$BNSZ`(r4) 1323 $LD r7,`5*$BNSZ`(r5) 1324 $UMULL r8,r6,r7 1325 $UMULH r9,r6,r7 1326 addc r11,r11,r8 1327 adde r12,r12,r9 1328 addze r10,r10 1329 #mul_add_c(a[3],b[4],c2,c3,c1); 1330 $LD r6,`3*$BNSZ`(r4) 1331 $LD r7,`4*$BNSZ`(r5) 1332 $UMULL r8,r6,r7 1333 $UMULH r9,r6,r7 1334 addc r11,r11,r8 1335 adde r12,r12,r9 1336 addze r10,r10 1337 #mul_add_c(a[4],b[3],c2,c3,c1); 1338 $LD r6,`4*$BNSZ`(r4) 1339 $LD r7,`3*$BNSZ`(r5) 1340 $UMULL r8,r6,r7 1341 $UMULH r9,r6,r7 1342 addc r11,r11,r8 1343 adde r12,r12,r9 1344 addze r10,r10 1345 #mul_add_c(a[5],b[2],c2,c3,c1); 1346 $LD r6,`5*$BNSZ`(r4) 1347 $LD r7,`2*$BNSZ`(r5) 1348 $UMULL r8,r6,r7 1349 $UMULH r9,r6,r7 1350 addc r11,r11,r8 1351 adde r12,r12,r9 1352 addze r10,r10 1353 #mul_add_c(a[6],b[1],c2,c3,c1); 1354 $LD r6,`6*$BNSZ`(r4) 1355 $LD r7,`1*$BNSZ`(r5) 1356 $UMULL r8,r6,r7 1357 $UMULH r9,r6,r7 1358 addc r11,r11,r8 1359 adde r12,r12,r9 1360 addze r10,r10 1361 #mul_add_c(a[7],b[0],c2,c3,c1); 1362 $LD r6,`7*$BNSZ`(r4) 1363 $LD r7,`0*$BNSZ`(r5) 1364 $UMULL r8,r6,r7 1365 $UMULH r9,r6,r7 1366 addc r11,r11,r8 1367 adde r12,r12,r9 1368 addze r10,r10 1369 $ST r11,`7*$BNSZ`(r3) #r[7]=c2; 1370 #mul_add_c(a[7],b[1],c3,c1,c2); 1371 $LD r7,`1*$BNSZ`(r5) 1372 $UMULL r8,r6,r7 1373 $UMULH r9,r6,r7 1374 addc r12,r12,r8 1375 adde r10,r10,r9 1376 addze r11,r0 1377 #mul_add_c(a[6],b[2],c3,c1,c2); 1378 $LD r6,`6*$BNSZ`(r4) 1379 $LD r7,`2*$BNSZ`(r5) 1380 $UMULL r8,r6,r7 1381 $UMULH r9,r6,r7 1382 addc r12,r12,r8 1383 adde r10,r10,r9 1384 addze r11,r11 1385 #mul_add_c(a[5],b[3],c3,c1,c2); 1386 $LD r6,`5*$BNSZ`(r4) 1387 $LD r7,`3*$BNSZ`(r5) 1388 $UMULL r8,r6,r7 1389 $UMULH r9,r6,r7 1390 addc r12,r12,r8 1391 adde r10,r10,r9 1392 addze r11,r11 1393 #mul_add_c(a[4],b[4],c3,c1,c2); 1394 $LD r6,`4*$BNSZ`(r4) 1395 $LD r7,`4*$BNSZ`(r5) 1396 $UMULL r8,r6,r7 1397 $UMULH r9,r6,r7 1398 addc r12,r12,r8 1399 adde r10,r10,r9 1400 addze r11,r11 1401 #mul_add_c(a[3],b[5],c3,c1,c2); 1402 $LD r6,`3*$BNSZ`(r4) 1403 $LD r7,`5*$BNSZ`(r5) 1404 $UMULL r8,r6,r7 1405 $UMULH r9,r6,r7 1406 addc r12,r12,r8 1407 adde r10,r10,r9 1408 addze r11,r11 1409 #mul_add_c(a[2],b[6],c3,c1,c2); 1410 $LD r6,`2*$BNSZ`(r4) 1411 $LD r7,`6*$BNSZ`(r5) 1412 $UMULL r8,r6,r7 1413 $UMULH r9,r6,r7 1414 addc r12,r12,r8 1415 adde r10,r10,r9 1416 addze r11,r11 1417 #mul_add_c(a[1],b[7],c3,c1,c2); 1418 $LD r6,`1*$BNSZ`(r4) 1419 $LD r7,`7*$BNSZ`(r5) 1420 $UMULL r8,r6,r7 1421 $UMULH r9,r6,r7 1422 addc r12,r12,r8 1423 adde r10,r10,r9 1424 addze r11,r11 1425 $ST r12,`8*$BNSZ`(r3) #r[8]=c3; 1426 #mul_add_c(a[2],b[7],c1,c2,c3); 1427 $LD r6,`2*$BNSZ`(r4) 1428 $UMULL r8,r6,r7 1429 $UMULH r9,r6,r7 1430 addc r10,r10,r8 1431 adde r11,r11,r9 1432 addze r12,r0 1433 #mul_add_c(a[3],b[6],c1,c2,c3); 1434 $LD r6,`3*$BNSZ`(r4) 1435 $LD r7,`6*$BNSZ`(r5) 1436 $UMULL r8,r6,r7 1437 $UMULH r9,r6,r7 1438 addc r10,r10,r8 1439 adde r11,r11,r9 1440 addze r12,r12 1441 #mul_add_c(a[4],b[5],c1,c2,c3); 1442 $LD r6,`4*$BNSZ`(r4) 1443 $LD r7,`5*$BNSZ`(r5) 1444 $UMULL r8,r6,r7 1445 $UMULH r9,r6,r7 1446 addc r10,r10,r8 1447 adde r11,r11,r9 1448 addze r12,r12 1449 #mul_add_c(a[5],b[4],c1,c2,c3); 1450 $LD r6,`5*$BNSZ`(r4) 1451 $LD r7,`4*$BNSZ`(r5) 1452 $UMULL r8,r6,r7 1453 $UMULH r9,r6,r7 1454 addc r10,r10,r8 1455 adde r11,r11,r9 1456 addze r12,r12 1457 #mul_add_c(a[6],b[3],c1,c2,c3); 1458 $LD r6,`6*$BNSZ`(r4) 1459 $LD r7,`3*$BNSZ`(r5) 1460 $UMULL r8,r6,r7 1461 $UMULH r9,r6,r7 1462 addc r10,r10,r8 1463 adde r11,r11,r9 1464 addze r12,r12 1465 #mul_add_c(a[7],b[2],c1,c2,c3); 1466 $LD r6,`7*$BNSZ`(r4) 1467 $LD r7,`2*$BNSZ`(r5) 1468 $UMULL r8,r6,r7 1469 $UMULH r9,r6,r7 1470 addc r10,r10,r8 1471 adde r11,r11,r9 1472 addze r12,r12 1473 $ST r10,`9*$BNSZ`(r3) #r[9]=c1; 1474 #mul_add_c(a[7],b[3],c2,c3,c1); 1475 $LD r7,`3*$BNSZ`(r5) 1476 $UMULL r8,r6,r7 1477 $UMULH r9,r6,r7 1478 addc r11,r11,r8 1479 adde r12,r12,r9 1480 addze r10,r0 1481 #mul_add_c(a[6],b[4],c2,c3,c1); 1482 $LD r6,`6*$BNSZ`(r4) 1483 $LD r7,`4*$BNSZ`(r5) 1484 $UMULL r8,r6,r7 1485 $UMULH r9,r6,r7 1486 addc r11,r11,r8 1487 adde r12,r12,r9 1488 addze r10,r10 1489 #mul_add_c(a[5],b[5],c2,c3,c1); 1490 $LD r6,`5*$BNSZ`(r4) 1491 $LD r7,`5*$BNSZ`(r5) 1492 $UMULL r8,r6,r7 1493 $UMULH r9,r6,r7 1494 addc r11,r11,r8 1495 adde r12,r12,r9 1496 addze r10,r10 1497 #mul_add_c(a[4],b[6],c2,c3,c1); 1498 $LD r6,`4*$BNSZ`(r4) 1499 $LD r7,`6*$BNSZ`(r5) 1500 $UMULL r8,r6,r7 1501 $UMULH r9,r6,r7 1502 addc r11,r11,r8 1503 adde r12,r12,r9 1504 addze r10,r10 1505 #mul_add_c(a[3],b[7],c2,c3,c1); 1506 $LD r6,`3*$BNSZ`(r4) 1507 $LD r7,`7*$BNSZ`(r5) 1508 $UMULL r8,r6,r7 1509 $UMULH r9,r6,r7 1510 addc r11,r11,r8 1511 adde r12,r12,r9 1512 addze r10,r10 1513 $ST r11,`10*$BNSZ`(r3) #r[10]=c2; 1514 #mul_add_c(a[4],b[7],c3,c1,c2); 1515 $LD r6,`4*$BNSZ`(r4) 1516 $UMULL r8,r6,r7 1517 $UMULH r9,r6,r7 1518 addc r12,r12,r8 1519 adde r10,r10,r9 1520 addze r11,r0 1521 #mul_add_c(a[5],b[6],c3,c1,c2); 1522 $LD r6,`5*$BNSZ`(r4) 1523 $LD r7,`6*$BNSZ`(r5) 1524 $UMULL r8,r6,r7 1525 $UMULH r9,r6,r7 1526 addc r12,r12,r8 1527 adde r10,r10,r9 1528 addze r11,r11 1529 #mul_add_c(a[6],b[5],c3,c1,c2); 1530 $LD r6,`6*$BNSZ`(r4) 1531 $LD r7,`5*$BNSZ`(r5) 1532 $UMULL r8,r6,r7 1533 $UMULH r9,r6,r7 1534 addc r12,r12,r8 1535 adde r10,r10,r9 1536 addze r11,r11 1537 #mul_add_c(a[7],b[4],c3,c1,c2); 1538 $LD r6,`7*$BNSZ`(r4) 1539 $LD r7,`4*$BNSZ`(r5) 1540 $UMULL r8,r6,r7 1541 $UMULH r9,r6,r7 1542 addc r12,r12,r8 1543 adde r10,r10,r9 1544 addze r11,r11 1545 $ST r12,`11*$BNSZ`(r3) #r[11]=c3; 1546 #mul_add_c(a[7],b[5],c1,c2,c3); 1547 $LD r7,`5*$BNSZ`(r5) 1548 $UMULL r8,r6,r7 1549 $UMULH r9,r6,r7 1550 addc r10,r10,r8 1551 adde r11,r11,r9 1552 addze r12,r0 1553 #mul_add_c(a[6],b[6],c1,c2,c3); 1554 $LD r6,`6*$BNSZ`(r4) 1555 $LD r7,`6*$BNSZ`(r5) 1556 $UMULL r8,r6,r7 1557 $UMULH r9,r6,r7 1558 addc r10,r10,r8 1559 adde r11,r11,r9 1560 addze r12,r12 1561 #mul_add_c(a[5],b[7],c1,c2,c3); 1562 $LD r6,`5*$BNSZ`(r4) 1563 $LD r7,`7*$BNSZ`(r5) 1564 $UMULL r8,r6,r7 1565 $UMULH r9,r6,r7 1566 addc r10,r10,r8 1567 adde r11,r11,r9 1568 addze r12,r12 1569 $ST r10,`12*$BNSZ`(r3) #r[12]=c1; 1570 #mul_add_c(a[6],b[7],c2,c3,c1); 1571 $LD r6,`6*$BNSZ`(r4) 1572 $UMULL r8,r6,r7 1573 $UMULH r9,r6,r7 1574 addc r11,r11,r8 1575 adde r12,r12,r9 1576 addze r10,r0 1577 #mul_add_c(a[7],b[6],c2,c3,c1); 1578 $LD r6,`7*$BNSZ`(r4) 1579 $LD r7,`6*$BNSZ`(r5) 1580 $UMULL r8,r6,r7 1581 $UMULH r9,r6,r7 1582 addc r11,r11,r8 1583 adde r12,r12,r9 1584 addze r10,r10 1585 $ST r11,`13*$BNSZ`(r3) #r[13]=c2; 1586 #mul_add_c(a[7],b[7],c3,c1,c2); 1587 $LD r7,`7*$BNSZ`(r5) 1588 $UMULL r8,r6,r7 1589 $UMULH r9,r6,r7 1590 addc r12,r12,r8 1591 adde r10,r10,r9 1592 $ST r12,`14*$BNSZ`(r3) #r[14]=c3; 1593 $ST r10,`15*$BNSZ`(r3) #r[15]=c1; 1594 bclr BO_ALWAYS,CR0_LT 1595 .long 0x00000000 1596 1597# 1598# NOTE: The following label name should be changed to 1599# "bn_sub_words" i.e. remove the first dot 1600# for the gcc compiler. This should be automatically 1601# done in the build 1602# 1603# 1604.align 4 1605.bn_sub_words: 1606# 1607# Handcoded version of bn_sub_words 1608# 1609#BN_ULONG bn_sub_words(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n) 1610# 1611# r3 = r 1612# r4 = a 1613# r5 = b 1614# r6 = n 1615# 1616# Note: No loop unrolling done since this is not a performance 1617# critical loop. 1618 1619 xor r0,r0,r0 #set r0 = 0 1620# 1621# check for r6 = 0 AND set carry bit. 1622# 1623 subfc. r7,r0,r6 # If r6 is 0 then result is 0. 1624 # if r6 > 0 then result !=0 1625 # In either case carry bit is set. 1626 bc BO_IF,CR0_EQ,Lppcasm_sub_adios 1627 addi r4,r4,-$BNSZ 1628 addi r3,r3,-$BNSZ 1629 addi r5,r5,-$BNSZ 1630 mtctr r6 1631Lppcasm_sub_mainloop: 1632 $LDU r7,$BNSZ(r4) 1633 $LDU r8,$BNSZ(r5) 1634 subfe r6,r8,r7 # r6 = r7+carry bit + onescomplement(r8) 1635 # if carry = 1 this is r7-r8. Else it 1636 # is r7-r8 -1 as we need. 1637 $STU r6,$BNSZ(r3) 1638 bc BO_dCTR_NZERO,CR0_EQ,Lppcasm_sub_mainloop 1639Lppcasm_sub_adios: 1640 subfze r3,r0 # if carry bit is set then r3 = 0 else -1 1641 andi. r3,r3,1 # keep only last bit. 1642 bclr BO_ALWAYS,CR0_LT 1643 .long 0x00000000 1644 1645 1646# 1647# NOTE: The following label name should be changed to 1648# "bn_add_words" i.e. remove the first dot 1649# for the gcc compiler. This should be automatically 1650# done in the build 1651# 1652 1653.align 4 1654.bn_add_words: 1655# 1656# Handcoded version of bn_add_words 1657# 1658#BN_ULONG bn_add_words(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n) 1659# 1660# r3 = r 1661# r4 = a 1662# r5 = b 1663# r6 = n 1664# 1665# Note: No loop unrolling done since this is not a performance 1666# critical loop. 1667 1668 xor r0,r0,r0 1669# 1670# check for r6 = 0. Is this needed? 1671# 1672 addic. r6,r6,0 #test r6 and clear carry bit. 1673 bc BO_IF,CR0_EQ,Lppcasm_add_adios 1674 addi r4,r4,-$BNSZ 1675 addi r3,r3,-$BNSZ 1676 addi r5,r5,-$BNSZ 1677 mtctr r6 1678Lppcasm_add_mainloop: 1679 $LDU r7,$BNSZ(r4) 1680 $LDU r8,$BNSZ(r5) 1681 adde r8,r7,r8 1682 $STU r8,$BNSZ(r3) 1683 bc BO_dCTR_NZERO,CR0_EQ,Lppcasm_add_mainloop 1684Lppcasm_add_adios: 1685 addze r3,r0 #return carry bit. 1686 bclr BO_ALWAYS,CR0_LT 1687 .long 0x00000000 1688 1689# 1690# NOTE: The following label name should be changed to 1691# "bn_div_words" i.e. remove the first dot 1692# for the gcc compiler. This should be automatically 1693# done in the build 1694# 1695 1696.align 4 1697.bn_div_words: 1698# 1699# This is a cleaned up version of code generated by 1700# the AIX compiler. The only optimization is to use 1701# the PPC instruction to count leading zeros instead 1702# of call to num_bits_word. Since this was compiled 1703# only at level -O2 we can possibly squeeze it more? 1704# 1705# r3 = h 1706# r4 = l 1707# r5 = d 1708 1709 $UCMPI 0,r5,0 # compare r5 and 0 1710 bc BO_IF_NOT,CR0_EQ,Lppcasm_div1 # proceed if d!=0 1711 li r3,-1 # d=0 return -1 1712 bclr BO_ALWAYS,CR0_LT 1713Lppcasm_div1: 1714 xor r0,r0,r0 #r0=0 1715 li r8,$BITS 1716 $CNTLZ. r7,r5 #r7 = num leading 0s in d. 1717 bc BO_IF,CR0_EQ,Lppcasm_div2 #proceed if no leading zeros 1718 subf r8,r7,r8 #r8 = BN_num_bits_word(d) 1719 $SHR. r9,r3,r8 #are there any bits above r8'th? 1720 $TR 16,r9,r0 #if there're, signal to dump core... 1721Lppcasm_div2: 1722 $UCMP 0,r3,r5 #h>=d? 1723 bc BO_IF,CR0_LT,Lppcasm_div3 #goto Lppcasm_div3 if not 1724 subf r3,r5,r3 #h-=d ; 1725Lppcasm_div3: #r7 = BN_BITS2-i. so r7=i 1726 cmpi 0,0,r7,0 # is (i == 0)? 1727 bc BO_IF,CR0_EQ,Lppcasm_div4 1728 $SHL r3,r3,r7 # h = (h<< i) 1729 $SHR r8,r4,r8 # r8 = (l >> BN_BITS2 -i) 1730 $SHL r5,r5,r7 # d<<=i 1731 or r3,r3,r8 # h = (h<<i)|(l>>(BN_BITS2-i)) 1732 $SHL r4,r4,r7 # l <<=i 1733Lppcasm_div4: 1734 $SHRI r9,r5,`$BITS/2` # r9 = dh 1735 # dl will be computed when needed 1736 # as it saves registers. 1737 li r6,2 #r6=2 1738 mtctr r6 #counter will be in count. 1739Lppcasm_divouterloop: 1740 $SHRI r8,r3,`$BITS/2` #r8 = (h>>BN_BITS4) 1741 $SHRI r11,r4,`$BITS/2` #r11= (l&BN_MASK2h)>>BN_BITS4 1742 # compute here for innerloop. 1743 $UCMP 0,r8,r9 # is (h>>BN_BITS4)==dh 1744 bc BO_IF_NOT,CR0_EQ,Lppcasm_div5 # goto Lppcasm_div5 if not 1745 1746 li r8,-1 1747 $CLRU r8,r8,`$BITS/2` #q = BN_MASK2l 1748 b Lppcasm_div6 1749Lppcasm_div5: 1750 $UDIV r8,r3,r9 #q = h/dh 1751Lppcasm_div6: 1752 $UMULL r12,r9,r8 #th = q*dh 1753 $CLRU r10,r5,`$BITS/2` #r10=dl 1754 $UMULL r6,r8,r10 #tl = q*dl 1755 1756Lppcasm_divinnerloop: 1757 subf r10,r12,r3 #t = h -th 1758 $SHRI r7,r10,`$BITS/2` #r7= (t &BN_MASK2H), sort of... 1759 addic. r7,r7,0 #test if r7 == 0. used below. 1760 # now want to compute 1761 # r7 = (t<<BN_BITS4)|((l&BN_MASK2h)>>BN_BITS4) 1762 # the following 2 instructions do that 1763 $SHLI r7,r10,`$BITS/2` # r7 = (t<<BN_BITS4) 1764 or r7,r7,r11 # r7|=((l&BN_MASK2h)>>BN_BITS4) 1765 $UCMP 1,r6,r7 # compare (tl <= r7) 1766 bc BO_IF_NOT,CR0_EQ,Lppcasm_divinnerexit 1767 bc BO_IF_NOT,CR1_FEX,Lppcasm_divinnerexit 1768 addi r8,r8,-1 #q-- 1769 subf r12,r9,r12 #th -=dh 1770 $CLRU r10,r5,`$BITS/2` #r10=dl. t is no longer needed in loop. 1771 subf r6,r10,r6 #tl -=dl 1772 b Lppcasm_divinnerloop 1773Lppcasm_divinnerexit: 1774 $SHRI r10,r6,`$BITS/2` #t=(tl>>BN_BITS4) 1775 $SHLI r11,r6,`$BITS/2` #tl=(tl<<BN_BITS4)&BN_MASK2h; 1776 $UCMP 1,r4,r11 # compare l and tl 1777 add r12,r12,r10 # th+=t 1778 bc BO_IF_NOT,CR1_FX,Lppcasm_div7 # if (l>=tl) goto Lppcasm_div7 1779 addi r12,r12,1 # th++ 1780Lppcasm_div7: 1781 subf r11,r11,r4 #r11=l-tl 1782 $UCMP 1,r3,r12 #compare h and th 1783 bc BO_IF_NOT,CR1_FX,Lppcasm_div8 #if (h>=th) goto Lppcasm_div8 1784 addi r8,r8,-1 # q-- 1785 add r3,r5,r3 # h+=d 1786Lppcasm_div8: 1787 subf r12,r12,r3 #r12 = h-th 1788 $SHLI r4,r11,`$BITS/2` #l=(l&BN_MASK2l)<<BN_BITS4 1789 # want to compute 1790 # h = ((h<<BN_BITS4)|(l>>BN_BITS4))&BN_MASK2 1791 # the following 2 instructions will do this. 1792 $INSR r11,r12,`$BITS/2`,`$BITS/2` # r11 is the value we want rotated $BITS/2. 1793 $ROTL r3,r11,`$BITS/2` # rotate by $BITS/2 and store in r3 1794 bc BO_dCTR_ZERO,CR0_EQ,Lppcasm_div9#if (count==0) break ; 1795 $SHLI r0,r8,`$BITS/2` #ret =q<<BN_BITS4 1796 b Lppcasm_divouterloop 1797Lppcasm_div9: 1798 or r3,r8,r0 1799 bclr BO_ALWAYS,CR0_LT 1800 .long 0x00000000 1801 1802# 1803# NOTE: The following label name should be changed to 1804# "bn_sqr_words" i.e. remove the first dot 1805# for the gcc compiler. This should be automatically 1806# done in the build 1807# 1808.align 4 1809.bn_sqr_words: 1810# 1811# Optimized version of bn_sqr_words 1812# 1813# void bn_sqr_words(BN_ULONG *r, BN_ULONG *a, int n) 1814# 1815# r3 = r 1816# r4 = a 1817# r5 = n 1818# 1819# r6 = a[i]. 1820# r7,r8 = product. 1821# 1822# No unrolling done here. Not performance critical. 1823 1824 addic. r5,r5,0 #test r5. 1825 bc BO_IF,CR0_EQ,Lppcasm_sqr_adios 1826 addi r4,r4,-$BNSZ 1827 addi r3,r3,-$BNSZ 1828 mtctr r5 1829Lppcasm_sqr_mainloop: 1830 #sqr(r[0],r[1],a[0]); 1831 $LDU r6,$BNSZ(r4) 1832 $UMULL r7,r6,r6 1833 $UMULH r8,r6,r6 1834 $STU r7,$BNSZ(r3) 1835 $STU r8,$BNSZ(r3) 1836 bc BO_dCTR_NZERO,CR0_EQ,Lppcasm_sqr_mainloop 1837Lppcasm_sqr_adios: 1838 bclr BO_ALWAYS,CR0_LT 1839 .long 0x00000000 1840 1841 1842# 1843# NOTE: The following label name should be changed to 1844# "bn_mul_words" i.e. remove the first dot 1845# for the gcc compiler. This should be automatically 1846# done in the build 1847# 1848 1849.align 4 1850.bn_mul_words: 1851# 1852# BN_ULONG bn_mul_words(BN_ULONG *rp, BN_ULONG *ap, int num, BN_ULONG w) 1853# 1854# r3 = rp 1855# r4 = ap 1856# r5 = num 1857# r6 = w 1858 xor r0,r0,r0 1859 xor r12,r12,r12 # used for carry 1860 rlwinm. r7,r5,30,2,31 # num >> 2 1861 bc BO_IF,CR0_EQ,Lppcasm_mw_REM 1862 mtctr r7 1863Lppcasm_mw_LOOP: 1864 #mul(rp[0],ap[0],w,c1); 1865 $LD r8,`0*$BNSZ`(r4) 1866 $UMULL r9,r6,r8 1867 $UMULH r10,r6,r8 1868 addc r9,r9,r12 1869 #addze r10,r10 #carry is NOT ignored. 1870 #will be taken care of 1871 #in second spin below 1872 #using adde. 1873 $ST r9,`0*$BNSZ`(r3) 1874 #mul(rp[1],ap[1],w,c1); 1875 $LD r8,`1*$BNSZ`(r4) 1876 $UMULL r11,r6,r8 1877 $UMULH r12,r6,r8 1878 adde r11,r11,r10 1879 #addze r12,r12 1880 $ST r11,`1*$BNSZ`(r3) 1881 #mul(rp[2],ap[2],w,c1); 1882 $LD r8,`2*$BNSZ`(r4) 1883 $UMULL r9,r6,r8 1884 $UMULH r10,r6,r8 1885 adde r9,r9,r12 1886 #addze r10,r10 1887 $ST r9,`2*$BNSZ`(r3) 1888 #mul_add(rp[3],ap[3],w,c1); 1889 $LD r8,`3*$BNSZ`(r4) 1890 $UMULL r11,r6,r8 1891 $UMULH r12,r6,r8 1892 adde r11,r11,r10 1893 addze r12,r12 #this spin we collect carry into 1894 #r12 1895 $ST r11,`3*$BNSZ`(r3) 1896 1897 addi r3,r3,`4*$BNSZ` 1898 addi r4,r4,`4*$BNSZ` 1899 bc BO_dCTR_NZERO,CR0_EQ,Lppcasm_mw_LOOP 1900 1901Lppcasm_mw_REM: 1902 andi. r5,r5,0x3 1903 bc BO_IF,CR0_EQ,Lppcasm_mw_OVER 1904 #mul(rp[0],ap[0],w,c1); 1905 $LD r8,`0*$BNSZ`(r4) 1906 $UMULL r9,r6,r8 1907 $UMULH r10,r6,r8 1908 addc r9,r9,r12 1909 addze r10,r10 1910 $ST r9,`0*$BNSZ`(r3) 1911 addi r12,r10,0 1912 1913 addi r5,r5,-1 1914 cmpli 0,0,r5,0 1915 bc BO_IF,CR0_EQ,Lppcasm_mw_OVER 1916 1917 1918 #mul(rp[1],ap[1],w,c1); 1919 $LD r8,`1*$BNSZ`(r4) 1920 $UMULL r9,r6,r8 1921 $UMULH r10,r6,r8 1922 addc r9,r9,r12 1923 addze r10,r10 1924 $ST r9,`1*$BNSZ`(r3) 1925 addi r12,r10,0 1926 1927 addi r5,r5,-1 1928 cmpli 0,0,r5,0 1929 bc BO_IF,CR0_EQ,Lppcasm_mw_OVER 1930 1931 #mul_add(rp[2],ap[2],w,c1); 1932 $LD r8,`2*$BNSZ`(r4) 1933 $UMULL r9,r6,r8 1934 $UMULH r10,r6,r8 1935 addc r9,r9,r12 1936 addze r10,r10 1937 $ST r9,`2*$BNSZ`(r3) 1938 addi r12,r10,0 1939 1940Lppcasm_mw_OVER: 1941 addi r3,r12,0 1942 bclr BO_ALWAYS,CR0_LT 1943 .long 0x00000000 1944 1945# 1946# NOTE: The following label name should be changed to 1947# "bn_mul_add_words" i.e. remove the first dot 1948# for the gcc compiler. This should be automatically 1949# done in the build 1950# 1951 1952.align 4 1953.bn_mul_add_words: 1954# 1955# BN_ULONG bn_mul_add_words(BN_ULONG *rp, BN_ULONG *ap, int num, BN_ULONG w) 1956# 1957# r3 = rp 1958# r4 = ap 1959# r5 = num 1960# r6 = w 1961# 1962# empirical evidence suggests that unrolled version performs best!! 1963# 1964 xor r0,r0,r0 #r0 = 0 1965 xor r12,r12,r12 #r12 = 0 . used for carry 1966 rlwinm. r7,r5,30,2,31 # num >> 2 1967 bc BO_IF,CR0_EQ,Lppcasm_maw_leftover # if (num < 4) go LPPCASM_maw_leftover 1968 mtctr r7 1969Lppcasm_maw_mainloop: 1970 #mul_add(rp[0],ap[0],w,c1); 1971 $LD r8,`0*$BNSZ`(r4) 1972 $LD r11,`0*$BNSZ`(r3) 1973 $UMULL r9,r6,r8 1974 $UMULH r10,r6,r8 1975 addc r9,r9,r12 #r12 is carry. 1976 addze r10,r10 1977 addc r9,r9,r11 1978 #addze r10,r10 1979 #the above instruction addze 1980 #is NOT needed. Carry will NOT 1981 #be ignored. It's not affected 1982 #by multiply and will be collected 1983 #in the next spin 1984 $ST r9,`0*$BNSZ`(r3) 1985 1986 #mul_add(rp[1],ap[1],w,c1); 1987 $LD r8,`1*$BNSZ`(r4) 1988 $LD r9,`1*$BNSZ`(r3) 1989 $UMULL r11,r6,r8 1990 $UMULH r12,r6,r8 1991 adde r11,r11,r10 #r10 is carry. 1992 addze r12,r12 1993 addc r11,r11,r9 1994 #addze r12,r12 1995 $ST r11,`1*$BNSZ`(r3) 1996 1997 #mul_add(rp[2],ap[2],w,c1); 1998 $LD r8,`2*$BNSZ`(r4) 1999 $UMULL r9,r6,r8 2000 $LD r11,`2*$BNSZ`(r3) 2001 $UMULH r10,r6,r8 2002 adde r9,r9,r12 2003 addze r10,r10 2004 addc r9,r9,r11 2005 #addze r10,r10 2006 $ST r9,`2*$BNSZ`(r3) 2007 2008 #mul_add(rp[3],ap[3],w,c1); 2009 $LD r8,`3*$BNSZ`(r4) 2010 $UMULL r11,r6,r8 2011 $LD r9,`3*$BNSZ`(r3) 2012 $UMULH r12,r6,r8 2013 adde r11,r11,r10 2014 addze r12,r12 2015 addc r11,r11,r9 2016 addze r12,r12 2017 $ST r11,`3*$BNSZ`(r3) 2018 addi r3,r3,`4*$BNSZ` 2019 addi r4,r4,`4*$BNSZ` 2020 bc BO_dCTR_NZERO,CR0_EQ,Lppcasm_maw_mainloop 2021 2022Lppcasm_maw_leftover: 2023 andi. r5,r5,0x3 2024 bc BO_IF,CR0_EQ,Lppcasm_maw_adios 2025 addi r3,r3,-$BNSZ 2026 addi r4,r4,-$BNSZ 2027 #mul_add(rp[0],ap[0],w,c1); 2028 mtctr r5 2029 $LDU r8,$BNSZ(r4) 2030 $UMULL r9,r6,r8 2031 $UMULH r10,r6,r8 2032 $LDU r11,$BNSZ(r3) 2033 addc r9,r9,r11 2034 addze r10,r10 2035 addc r9,r9,r12 2036 addze r12,r10 2037 $ST r9,0(r3) 2038 2039 bc BO_dCTR_ZERO,CR0_EQ,Lppcasm_maw_adios 2040 #mul_add(rp[1],ap[1],w,c1); 2041 $LDU r8,$BNSZ(r4) 2042 $UMULL r9,r6,r8 2043 $UMULH r10,r6,r8 2044 $LDU r11,$BNSZ(r3) 2045 addc r9,r9,r11 2046 addze r10,r10 2047 addc r9,r9,r12 2048 addze r12,r10 2049 $ST r9,0(r3) 2050 2051 bc BO_dCTR_ZERO,CR0_EQ,Lppcasm_maw_adios 2052 #mul_add(rp[2],ap[2],w,c1); 2053 $LDU r8,$BNSZ(r4) 2054 $UMULL r9,r6,r8 2055 $UMULH r10,r6,r8 2056 $LDU r11,$BNSZ(r3) 2057 addc r9,r9,r11 2058 addze r10,r10 2059 addc r9,r9,r12 2060 addze r12,r10 2061 $ST r9,0(r3) 2062 2063Lppcasm_maw_adios: 2064 addi r3,r12,0 2065 bclr BO_ALWAYS,CR0_LT 2066 .long 0x00000000 2067 .align 4 2068EOF 2069 $data =~ s/\`([^\`]*)\`/eval $1/gem; 2070 2071 # if some assembler chokes on some simplified mnemonic, 2072 # this is the spot to fix it up, e.g.: 2073 # GNU as doesn't seem to accept cmplw, 32-bit unsigned compare 2074 $data =~ s/^(\s*)cmplw(\s+)([^,]+),(.*)/$1cmpl$2$3,0,$4/gm; 2075 # assembler X doesn't accept li, load immediate value 2076 #$data =~ s/^(\s*)li(\s+)([^,]+),(.*)/$1addi$2$3,0,$4/gm; 2077 # assembler Y chokes on apostrophes in comments 2078 $data =~ s/'//gm; 2079 return($data); 2080} 2081