12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232 |
- #! /usr/bin/env perl
- # Copyright 2012-2016 The OpenSSL Project Authors. All Rights Reserved.
- #
- # Licensed under the OpenSSL license (the "License"). You may not use
- # this file except in compliance with the License. You can obtain a copy
- # in the file LICENSE in the source distribution or at
- # https://www.openssl.org/source/license.html
- # ====================================================================
- # Written by David S. Miller and Andy Polyakov
- # The module is licensed under 2-clause BSD license.
- # November 2012. All rights reserved.
- # ====================================================================
- ######################################################################
- # Montgomery squaring-n-multiplication module for SPARC T4.
- #
- # The module consists of three parts:
- #
- # 1) collection of "single-op" subroutines that perform single
- # operation, Montgomery squaring or multiplication, on 512-,
- # 1024-, 1536- and 2048-bit operands;
- # 2) collection of "multi-op" subroutines that perform 5 squaring and
- # 1 multiplication operations on operands of above lengths;
- # 3) fall-back and helper VIS3 subroutines.
- #
- # RSA sign is dominated by multi-op subroutine, while RSA verify and
- # DSA - by single-op. Special note about 4096-bit RSA verify result.
- # Operands are too long for dedicated hardware and it's handled by
- # VIS3 code, which is why you don't see any improvement. It's surely
- # possible to improve it [by deploying 'mpmul' instruction], maybe in
- # the future...
- #
- # Performance improvement.
- #
- # 64-bit process, VIS3:
- # sign verify sign/s verify/s
- # rsa 1024 bits 0.000628s 0.000028s 1592.4 35434.4
- # rsa 2048 bits 0.003282s 0.000106s 304.7 9438.3
- # rsa 4096 bits 0.025866s 0.000340s 38.7 2940.9
- # dsa 1024 bits 0.000301s 0.000332s 3323.7 3013.9
- # dsa 2048 bits 0.001056s 0.001233s 946.9 810.8
- #
- # 64-bit process, this module:
- # sign verify sign/s verify/s
- # rsa 1024 bits 0.000256s 0.000016s 3904.4 61411.9
- # rsa 2048 bits 0.000946s 0.000029s 1056.8 34292.7
- # rsa 4096 bits 0.005061s 0.000340s 197.6 2940.5
- # dsa 1024 bits 0.000176s 0.000195s 5674.7 5130.5
- # dsa 2048 bits 0.000296s 0.000354s 3383.2 2827.6
- #
- ######################################################################
- # 32-bit process, VIS3:
- # sign verify sign/s verify/s
- # rsa 1024 bits 0.000665s 0.000028s 1504.8 35233.3
- # rsa 2048 bits 0.003349s 0.000106s 298.6 9433.4
- # rsa 4096 bits 0.025959s 0.000341s 38.5 2934.8
- # dsa 1024 bits 0.000320s 0.000341s 3123.3 2929.6
- # dsa 2048 bits 0.001101s 0.001260s 908.2 793.4
- #
- # 32-bit process, this module:
- # sign verify sign/s verify/s
- # rsa 1024 bits 0.000301s 0.000017s 3317.1 60240.0
- # rsa 2048 bits 0.001034s 0.000030s 966.9 33812.7
- # rsa 4096 bits 0.005244s 0.000341s 190.7 2935.4
- # dsa 1024 bits 0.000201s 0.000205s 4976.1 4879.2
- # dsa 2048 bits 0.000328s 0.000360s 3051.1 2774.2
- #
- # 32-bit code is prone to performance degradation as interrupt rate
- # dispatched to CPU executing the code grows. This is because in
- # standard process of handling interrupt in 32-bit process context
- # upper halves of most integer registers used as input or output are
- # zeroed. This renders result invalid, and operation has to be re-run.
- # If CPU is "bothered" with timer interrupts only, the penalty is
- # hardly measurable. But in order to mitigate this problem for higher
- # interrupt rates contemporary Linux kernel recognizes biased stack
- # even in 32-bit process context and preserves full register contents.
- # See http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=517ffce4e1a03aea979fe3a18a3dd1761a24fafb
- # for details.
- $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
- push(@INC,"${dir}","${dir}../../perlasm");
- require "sparcv9_modes.pl";
- $output = pop;
- open STDOUT,">$output";
- $code.=<<___;
- #include "sparc_arch.h"
- #ifdef __arch64__
- .register %g2,#scratch
- .register %g3,#scratch
- #endif
- .section ".text",#alloc,#execinstr
- #ifdef __PIC__
- SPARC_PIC_THUNK(%g1)
- #endif
- ___
- ########################################################################
- # Register layout for mont[mul|sqr] instructions.
- # For details see "Oracle SPARC Architecture 2011" manual at
- # http://www.oracle.com/technetwork/server-storage/sun-sparc-enterprise/documentation/.
- #
- my @R=map("%f".2*$_,(0..11,30,31,12..29));
- my @N=(map("%l$_",(0..7)),map("%o$_",(0..5))); @N=(@N,@N,@N[0..3]);
- my @A=(@N[0..13],@R[14..31]);
- my @B=(map("%i$_",(0..5)),map("%l$_",(0..7))); @B=(@B,@B,map("%o$_",(0..3)));
- ########################################################################
- # int bn_mul_mont_t4_$NUM(u64 *rp,const u64 *ap,const u64 *bp,
- # const u64 *np,const BN_ULONG *n0);
- #
- sub generate_bn_mul_mont_t4() {
- my $NUM=shift;
- my ($rp,$ap,$bp,$np,$sentinel)=map("%g$_",(1..5));
- $code.=<<___;
- .globl bn_mul_mont_t4_$NUM
- .align 32
- bn_mul_mont_t4_$NUM:
- #ifdef __arch64__
- mov 0,$sentinel
- mov -128,%g4
- #elif defined(SPARCV9_64BIT_STACK)
- SPARC_LOAD_ADDRESS_LEAF(OPENSSL_sparcv9cap_P,%g1,%g5)
- ld [%g1+0],%g1 ! OPENSSL_sparcv9_P[0]
- mov -2047,%g4
- and %g1,SPARCV9_64BIT_STACK,%g1
- movrz %g1,0,%g4
- mov -1,$sentinel
- add %g4,-128,%g4
- #else
- mov -1,$sentinel
- mov -128,%g4
- #endif
- sllx $sentinel,32,$sentinel
- save %sp,%g4,%sp
- #ifndef __arch64__
- save %sp,-128,%sp ! warm it up
- save %sp,-128,%sp
- save %sp,-128,%sp
- save %sp,-128,%sp
- save %sp,-128,%sp
- save %sp,-128,%sp
- restore
- restore
- restore
- restore
- restore
- restore
- #endif
- and %sp,1,%g4
- or $sentinel,%fp,%fp
- or %g4,$sentinel,$sentinel
- ! copy arguments to global registers
- mov %i0,$rp
- mov %i1,$ap
- mov %i2,$bp
- mov %i3,$np
- ld [%i4+0],%f1 ! load *n0
- ld [%i4+4],%f0
- fsrc2 %f0,%f60
- ___
- # load ap[$NUM] ########################################################
- $code.=<<___;
- save %sp,-128,%sp; or $sentinel,%fp,%fp
- ___
- for($i=0; $i<14 && $i<$NUM; $i++) {
- my $lo=$i<13?@A[$i+1]:"%o7";
- $code.=<<___;
- ld [$ap+$i*8+0],$lo
- ld [$ap+$i*8+4],@A[$i]
- sllx @A[$i],32,@A[$i]
- or $lo,@A[$i],@A[$i]
- ___
- }
- for(; $i<$NUM; $i++) {
- my ($hi,$lo)=("%f".2*($i%4),"%f".(2*($i%4)+1));
- $code.=<<___;
- ld [$ap+$i*8+0],$lo
- ld [$ap+$i*8+4],$hi
- fsrc2 $hi,@A[$i]
- ___
- }
- # load np[$NUM] ########################################################
- $code.=<<___;
- save %sp,-128,%sp; or $sentinel,%fp,%fp
- ___
- for($i=0; $i<14 && $i<$NUM; $i++) {
- my $lo=$i<13?@N[$i+1]:"%o7";
- $code.=<<___;
- ld [$np+$i*8+0],$lo
- ld [$np+$i*8+4],@N[$i]
- sllx @N[$i],32,@N[$i]
- or $lo,@N[$i],@N[$i]
- ___
- }
- $code.=<<___;
- save %sp,-128,%sp; or $sentinel,%fp,%fp
- ___
- for(; $i<28 && $i<$NUM; $i++) {
- my $lo=$i<27?@N[$i+1]:"%o7";
- $code.=<<___;
- ld [$np+$i*8+0],$lo
- ld [$np+$i*8+4],@N[$i]
- sllx @N[$i],32,@N[$i]
- or $lo,@N[$i],@N[$i]
- ___
- }
- $code.=<<___;
- save %sp,-128,%sp; or $sentinel,%fp,%fp
- ___
- for(; $i<$NUM; $i++) {
- my $lo=($i<$NUM-1)?@N[$i+1]:"%o7";
- $code.=<<___;
- ld [$np+$i*8+0],$lo
- ld [$np+$i*8+4],@N[$i]
- sllx @N[$i],32,@N[$i]
- or $lo,@N[$i],@N[$i]
- ___
- }
- $code.=<<___;
- cmp $ap,$bp
- be SIZE_T_CC,.Lmsquare_$NUM
- nop
- ___
- # load bp[$NUM] ########################################################
- $code.=<<___;
- save %sp,-128,%sp; or $sentinel,%fp,%fp
- ___
- for($i=0; $i<14 && $i<$NUM; $i++) {
- my $lo=$i<13?@B[$i+1]:"%o7";
- $code.=<<___;
- ld [$bp+$i*8+0],$lo
- ld [$bp+$i*8+4],@B[$i]
- sllx @B[$i],32,@B[$i]
- or $lo,@B[$i],@B[$i]
- ___
- }
- $code.=<<___;
- save %sp,-128,%sp; or $sentinel,%fp,%fp
- ___
- for(; $i<$NUM; $i++) {
- my $lo=($i<$NUM-1)?@B[$i+1]:"%o7";
- $code.=<<___;
- ld [$bp+$i*8+0],$lo
- ld [$bp+$i*8+4],@B[$i]
- sllx @B[$i],32,@B[$i]
- or $lo,@B[$i],@B[$i]
- ___
- }
- # magic ################################################################
- $code.=<<___;
- .word 0x81b02920+$NUM-1 ! montmul $NUM-1
- .Lmresume_$NUM:
- fbu,pn %fcc3,.Lmabort_$NUM
- #ifndef __arch64__
- and %fp,$sentinel,$sentinel
- brz,pn $sentinel,.Lmabort_$NUM
- #endif
- nop
- #ifdef __arch64__
- restore
- restore
- restore
- restore
- restore
- #else
- restore; and %fp,$sentinel,$sentinel
- restore; and %fp,$sentinel,$sentinel
- restore; and %fp,$sentinel,$sentinel
- restore; and %fp,$sentinel,$sentinel
- brz,pn $sentinel,.Lmabort1_$NUM
- restore
- #endif
- ___
- # save tp[$NUM] ########################################################
- for($i=0; $i<14 && $i<$NUM; $i++) {
- $code.=<<___;
- movxtod @A[$i],@R[$i]
- ___
- }
- $code.=<<___;
- #ifdef __arch64__
- restore
- #else
- and %fp,$sentinel,$sentinel
- restore
- and $sentinel,1,%o7
- and %fp,$sentinel,$sentinel
- srl %fp,0,%fp ! just in case?
- or %o7,$sentinel,$sentinel
- brz,a,pn $sentinel,.Lmdone_$NUM
- mov 0,%i0 ! return failure
- #endif
- ___
- for($i=0; $i<12 && $i<$NUM; $i++) {
- @R[$i] =~ /%f([0-9]+)/;
- my $lo = "%f".($1+1);
- $code.=<<___;
- st $lo,[$rp+$i*8+0]
- st @R[$i],[$rp+$i*8+4]
- ___
- }
- for(; $i<$NUM; $i++) {
- my ($hi,$lo)=("%f".2*($i%4),"%f".(2*($i%4)+1));
- $code.=<<___;
- fsrc2 @R[$i],$hi
- st $lo,[$rp+$i*8+0]
- st $hi,[$rp+$i*8+4]
- ___
- }
- $code.=<<___;
- mov 1,%i0 ! return success
- .Lmdone_$NUM:
- ret
- restore
- .Lmabort_$NUM:
- restore
- restore
- restore
- restore
- restore
- .Lmabort1_$NUM:
- restore
- mov 0,%i0 ! return failure
- ret
- restore
- .align 32
- .Lmsquare_$NUM:
- save %sp,-128,%sp; or $sentinel,%fp,%fp
- save %sp,-128,%sp; or $sentinel,%fp,%fp
- .word 0x81b02940+$NUM-1 ! montsqr $NUM-1
- ba .Lmresume_$NUM
- nop
- .type bn_mul_mont_t4_$NUM, #function
- .size bn_mul_mont_t4_$NUM, .-bn_mul_mont_t4_$NUM
- ___
- }
- for ($i=8;$i<=32;$i+=8) {
- &generate_bn_mul_mont_t4($i);
- }
- ########################################################################
- #
- sub load_ccr {
- my ($ptbl,$pwr,$ccr,$skip_wr)=@_;
- $code.=<<___;
- srl $pwr, 2, %o4
- and $pwr, 3, %o5
- and %o4, 7, %o4
- sll %o5, 3, %o5 ! offset within first cache line
- add %o5, $ptbl, $ptbl ! of the pwrtbl
- or %g0, 1, %o5
- sll %o5, %o4, $ccr
- ___
- $code.=<<___ if (!$skip_wr);
- wr $ccr, %g0, %ccr
- ___
- }
- sub load_b_pair {
- my ($pwrtbl,$B0,$B1)=@_;
- $code.=<<___;
- ldx [$pwrtbl+0*32], $B0
- ldx [$pwrtbl+8*32], $B1
- ldx [$pwrtbl+1*32], %o4
- ldx [$pwrtbl+9*32], %o5
- movvs %icc, %o4, $B0
- ldx [$pwrtbl+2*32], %o4
- movvs %icc, %o5, $B1
- ldx [$pwrtbl+10*32],%o5
- move %icc, %o4, $B0
- ldx [$pwrtbl+3*32], %o4
- move %icc, %o5, $B1
- ldx [$pwrtbl+11*32],%o5
- movneg %icc, %o4, $B0
- ldx [$pwrtbl+4*32], %o4
- movneg %icc, %o5, $B1
- ldx [$pwrtbl+12*32],%o5
- movcs %xcc, %o4, $B0
- ldx [$pwrtbl+5*32],%o4
- movcs %xcc, %o5, $B1
- ldx [$pwrtbl+13*32],%o5
- movvs %xcc, %o4, $B0
- ldx [$pwrtbl+6*32], %o4
- movvs %xcc, %o5, $B1
- ldx [$pwrtbl+14*32],%o5
- move %xcc, %o4, $B0
- ldx [$pwrtbl+7*32], %o4
- move %xcc, %o5, $B1
- ldx [$pwrtbl+15*32],%o5
- movneg %xcc, %o4, $B0
- add $pwrtbl,16*32, $pwrtbl
- movneg %xcc, %o5, $B1
- ___
- }
- sub load_b {
- my ($pwrtbl,$Bi)=@_;
- $code.=<<___;
- ldx [$pwrtbl+0*32], $Bi
- ldx [$pwrtbl+1*32], %o4
- ldx [$pwrtbl+2*32], %o5
- movvs %icc, %o4, $Bi
- ldx [$pwrtbl+3*32], %o4
- move %icc, %o5, $Bi
- ldx [$pwrtbl+4*32], %o5
- movneg %icc, %o4, $Bi
- ldx [$pwrtbl+5*32], %o4
- movcs %xcc, %o5, $Bi
- ldx [$pwrtbl+6*32], %o5
- movvs %xcc, %o4, $Bi
- ldx [$pwrtbl+7*32], %o4
- move %xcc, %o5, $Bi
- add $pwrtbl,8*32, $pwrtbl
- movneg %xcc, %o4, $Bi
- ___
- }
- ########################################################################
- # int bn_pwr5_mont_t4_$NUM(u64 *tp,const u64 *np,const BN_ULONG *n0,
- # const u64 *pwrtbl,int pwr,int stride);
- #
- sub generate_bn_pwr5_mont_t4() {
- my $NUM=shift;
- my ($tp,$np,$pwrtbl,$pwr,$sentinel)=map("%g$_",(1..5));
- $code.=<<___;
- .globl bn_pwr5_mont_t4_$NUM
- .align 32
- bn_pwr5_mont_t4_$NUM:
- #ifdef __arch64__
- mov 0,$sentinel
- mov -128,%g4
- #elif defined(SPARCV9_64BIT_STACK)
- SPARC_LOAD_ADDRESS_LEAF(OPENSSL_sparcv9cap_P,%g1,%g5)
- ld [%g1+0],%g1 ! OPENSSL_sparcv9_P[0]
- mov -2047,%g4
- and %g1,SPARCV9_64BIT_STACK,%g1
- movrz %g1,0,%g4
- mov -1,$sentinel
- add %g4,-128,%g4
- #else
- mov -1,$sentinel
- mov -128,%g4
- #endif
- sllx $sentinel,32,$sentinel
- save %sp,%g4,%sp
- #ifndef __arch64__
- save %sp,-128,%sp ! warm it up
- save %sp,-128,%sp
- save %sp,-128,%sp
- save %sp,-128,%sp
- save %sp,-128,%sp
- save %sp,-128,%sp
- restore
- restore
- restore
- restore
- restore
- restore
- #endif
- and %sp,1,%g4
- or $sentinel,%fp,%fp
- or %g4,$sentinel,$sentinel
- ! copy arguments to global registers
- mov %i0,$tp
- mov %i1,$np
- ld [%i2+0],%f1 ! load *n0
- ld [%i2+4],%f0
- mov %i3,$pwrtbl
- srl %i4,%g0,%i4 ! pack last arguments
- sllx %i5,32,$pwr
- or %i4,$pwr,$pwr
- fsrc2 %f0,%f60
- ___
- # load tp[$NUM] ########################################################
- $code.=<<___;
- save %sp,-128,%sp; or $sentinel,%fp,%fp
- ___
- for($i=0; $i<14 && $i<$NUM; $i++) {
- $code.=<<___;
- ldx [$tp+$i*8],@A[$i]
- ___
- }
- for(; $i<$NUM; $i++) {
- $code.=<<___;
- ldd [$tp+$i*8],@A[$i]
- ___
- }
- # load np[$NUM] ########################################################
- $code.=<<___;
- save %sp,-128,%sp; or $sentinel,%fp,%fp
- ___
- for($i=0; $i<14 && $i<$NUM; $i++) {
- $code.=<<___;
- ldx [$np+$i*8],@N[$i]
- ___
- }
- $code.=<<___;
- save %sp,-128,%sp; or $sentinel,%fp,%fp
- ___
- for(; $i<28 && $i<$NUM; $i++) {
- $code.=<<___;
- ldx [$np+$i*8],@N[$i]
- ___
- }
- $code.=<<___;
- save %sp,-128,%sp; or $sentinel,%fp,%fp
- ___
- for(; $i<$NUM; $i++) {
- $code.=<<___;
- ldx [$np+$i*8],@N[$i]
- ___
- }
- # load pwrtbl[pwr] ########################################################
- $code.=<<___;
- save %sp,-128,%sp; or $sentinel,%fp,%fp
- srlx $pwr, 32, %o4 ! unpack $pwr
- srl $pwr, %g0, %o5
- sub %o4, 5, %o4
- mov $pwrtbl, %o7
- sllx %o4, 32, $pwr ! re-pack $pwr
- or %o5, $pwr, $pwr
- srl %o5, %o4, %o5
- ___
- &load_ccr("%o7","%o5","%o4");
- $code.=<<___;
- b .Lstride_$NUM
- nop
- .align 16
- .Lstride_$NUM:
- ___
- for($i=0; $i<14 && $i<$NUM; $i+=2) {
- &load_b_pair("%o7",@B[$i],@B[$i+1]);
- }
- $code.=<<___;
- save %sp,-128,%sp; or $sentinel,%fp,%fp
- ___
- for(; $i<$NUM; $i+=2) {
- &load_b_pair("%i7",@B[$i],@B[$i+1]);
- }
- $code.=<<___;
- srax $pwr, 32, %o4 ! unpack $pwr
- srl $pwr, %g0, %o5
- sub %o4, 5, %o4
- mov $pwrtbl, %i7
- sllx %o4, 32, $pwr ! re-pack $pwr
- or %o5, $pwr, $pwr
- srl %o5, %o4, %o5
- ___
- &load_ccr("%i7","%o5","%o4",1);
- # magic ################################################################
- for($i=0; $i<5; $i++) {
- $code.=<<___;
- .word 0x81b02940+$NUM-1 ! montsqr $NUM-1
- fbu,pn %fcc3,.Labort_$NUM
- #ifndef __arch64__
- and %fp,$sentinel,$sentinel
- brz,pn $sentinel,.Labort_$NUM
- #endif
- nop
- ___
- }
- $code.=<<___;
- wr %o4, %g0, %ccr
- .word 0x81b02920+$NUM-1 ! montmul $NUM-1
- fbu,pn %fcc3,.Labort_$NUM
- #ifndef __arch64__
- and %fp,$sentinel,$sentinel
- brz,pn $sentinel,.Labort_$NUM
- #endif
- srax $pwr, 32, %o4
- #ifdef __arch64__
- brgez %o4,.Lstride_$NUM
- restore
- restore
- restore
- restore
- restore
- #else
- brgez %o4,.Lstride_$NUM
- restore; and %fp,$sentinel,$sentinel
- restore; and %fp,$sentinel,$sentinel
- restore; and %fp,$sentinel,$sentinel
- restore; and %fp,$sentinel,$sentinel
- brz,pn $sentinel,.Labort1_$NUM
- restore
- #endif
- ___
- # save tp[$NUM] ########################################################
- for($i=0; $i<14 && $i<$NUM; $i++) {
- $code.=<<___;
- movxtod @A[$i],@R[$i]
- ___
- }
- $code.=<<___;
- #ifdef __arch64__
- restore
- #else
- and %fp,$sentinel,$sentinel
- restore
- and $sentinel,1,%o7
- and %fp,$sentinel,$sentinel
- srl %fp,0,%fp ! just in case?
- or %o7,$sentinel,$sentinel
- brz,a,pn $sentinel,.Ldone_$NUM
- mov 0,%i0 ! return failure
- #endif
- ___
- for($i=0; $i<$NUM; $i++) {
- $code.=<<___;
- std @R[$i],[$tp+$i*8]
- ___
- }
- $code.=<<___;
- mov 1,%i0 ! return success
- .Ldone_$NUM:
- ret
- restore
- .Labort_$NUM:
- restore
- restore
- restore
- restore
- restore
- .Labort1_$NUM:
- restore
- mov 0,%i0 ! return failure
- ret
- restore
- .type bn_pwr5_mont_t4_$NUM, #function
- .size bn_pwr5_mont_t4_$NUM, .-bn_pwr5_mont_t4_$NUM
- ___
- }
- for ($i=8;$i<=32;$i+=8) {
- &generate_bn_pwr5_mont_t4($i);
- }
- {
- ########################################################################
- # Fall-back subroutines
- #
- # copy of bn_mul_mont_vis3 adjusted for vectors of 64-bit values
- #
- ($n0,$m0,$m1,$lo0,$hi0, $lo1,$hi1,$aj,$alo,$nj,$nlo,$tj)=
- (map("%g$_",(1..5)),map("%o$_",(0..5,7)));
- # int bn_mul_mont(
- $rp="%o0"; # u64 *rp,
- $ap="%o1"; # const u64 *ap,
- $bp="%o2"; # const u64 *bp,
- $np="%o3"; # const u64 *np,
- $n0p="%o4"; # const BN_ULONG *n0,
- $num="%o5"; # int num); # caller ensures that num is >=3
- $code.=<<___;
- .globl bn_mul_mont_t4
- .align 32
- bn_mul_mont_t4:
- add %sp, STACK_BIAS, %g4 ! real top of stack
- sll $num, 3, $num ! size in bytes
- add $num, 63, %g1
- andn %g1, 63, %g1 ! buffer size rounded up to 64 bytes
- sub %g4, %g1, %g1
- andn %g1, 63, %g1 ! align at 64 byte
- sub %g1, STACK_FRAME, %g1 ! new top of stack
- sub %g1, %g4, %g1
- save %sp, %g1, %sp
- ___
- # +-------------------------------+<----- %sp
- # . .
- # +-------------------------------+<----- aligned at 64 bytes
- # | __int64 tmp[0] |
- # +-------------------------------+
- # . .
- # . .
- # +-------------------------------+<----- aligned at 64 bytes
- # . .
- ($rp,$ap,$bp,$np,$n0p,$num)=map("%i$_",(0..5));
- ($t0,$t1,$t2,$t3,$cnt,$tp,$bufsz)=map("%l$_",(0..7));
- ($ovf,$i)=($t0,$t1);
- $code.=<<___;
- ld [$n0p+0], $t0 ! pull n0[0..1] value
- ld [$n0p+4], $t1
- add %sp, STACK_BIAS+STACK_FRAME, $tp
- ldx [$bp+0], $m0 ! m0=bp[0]
- sllx $t1, 32, $n0
- add $bp, 8, $bp
- or $t0, $n0, $n0
- ldx [$ap+0], $aj ! ap[0]
- mulx $aj, $m0, $lo0 ! ap[0]*bp[0]
- umulxhi $aj, $m0, $hi0
- ldx [$ap+8], $aj ! ap[1]
- add $ap, 16, $ap
- ldx [$np+0], $nj ! np[0]
- mulx $lo0, $n0, $m1 ! "tp[0]"*n0
- mulx $aj, $m0, $alo ! ap[1]*bp[0]
- umulxhi $aj, $m0, $aj ! ahi=aj
- mulx $nj, $m1, $lo1 ! np[0]*m1
- umulxhi $nj, $m1, $hi1
- ldx [$np+8], $nj ! np[1]
- addcc $lo0, $lo1, $lo1
- add $np, 16, $np
- addxc %g0, $hi1, $hi1
- mulx $nj, $m1, $nlo ! np[1]*m1
- umulxhi $nj, $m1, $nj ! nhi=nj
- ba .L1st
- sub $num, 24, $cnt ! cnt=num-3
- .align 16
- .L1st:
- addcc $alo, $hi0, $lo0
- addxc $aj, %g0, $hi0
- ldx [$ap+0], $aj ! ap[j]
- addcc $nlo, $hi1, $lo1
- add $ap, 8, $ap
- addxc $nj, %g0, $hi1 ! nhi=nj
- ldx [$np+0], $nj ! np[j]
- mulx $aj, $m0, $alo ! ap[j]*bp[0]
- add $np, 8, $np
- umulxhi $aj, $m0, $aj ! ahi=aj
- mulx $nj, $m1, $nlo ! np[j]*m1
- addcc $lo0, $lo1, $lo1 ! np[j]*m1+ap[j]*bp[0]
- umulxhi $nj, $m1, $nj ! nhi=nj
- addxc %g0, $hi1, $hi1
- stxa $lo1, [$tp]0xe2 ! tp[j-1]
- add $tp, 8, $tp ! tp++
- brnz,pt $cnt, .L1st
- sub $cnt, 8, $cnt ! j--
- !.L1st
- addcc $alo, $hi0, $lo0
- addxc $aj, %g0, $hi0 ! ahi=aj
- addcc $nlo, $hi1, $lo1
- addxc $nj, %g0, $hi1
- addcc $lo0, $lo1, $lo1 ! np[j]*m1+ap[j]*bp[0]
- addxc %g0, $hi1, $hi1
- stxa $lo1, [$tp]0xe2 ! tp[j-1]
- add $tp, 8, $tp
- addcc $hi0, $hi1, $hi1
- addxc %g0, %g0, $ovf ! upmost overflow bit
- stxa $hi1, [$tp]0xe2
- add $tp, 8, $tp
- ba .Louter
- sub $num, 16, $i ! i=num-2
- .align 16
- .Louter:
- ldx [$bp+0], $m0 ! m0=bp[i]
- add $bp, 8, $bp
- sub $ap, $num, $ap ! rewind
- sub $np, $num, $np
- sub $tp, $num, $tp
- ldx [$ap+0], $aj ! ap[0]
- ldx [$np+0], $nj ! np[0]
- mulx $aj, $m0, $lo0 ! ap[0]*bp[i]
- ldx [$tp], $tj ! tp[0]
- umulxhi $aj, $m0, $hi0
- ldx [$ap+8], $aj ! ap[1]
- addcc $lo0, $tj, $lo0 ! ap[0]*bp[i]+tp[0]
- mulx $aj, $m0, $alo ! ap[1]*bp[i]
- addxc %g0, $hi0, $hi0
- mulx $lo0, $n0, $m1 ! tp[0]*n0
- umulxhi $aj, $m0, $aj ! ahi=aj
- mulx $nj, $m1, $lo1 ! np[0]*m1
- add $ap, 16, $ap
- umulxhi $nj, $m1, $hi1
- ldx [$np+8], $nj ! np[1]
- add $np, 16, $np
- addcc $lo1, $lo0, $lo1
- mulx $nj, $m1, $nlo ! np[1]*m1
- addxc %g0, $hi1, $hi1
- umulxhi $nj, $m1, $nj ! nhi=nj
- ba .Linner
- sub $num, 24, $cnt ! cnt=num-3
- .align 16
- .Linner:
- addcc $alo, $hi0, $lo0
- ldx [$tp+8], $tj ! tp[j]
- addxc $aj, %g0, $hi0 ! ahi=aj
- ldx [$ap+0], $aj ! ap[j]
- add $ap, 8, $ap
- addcc $nlo, $hi1, $lo1
- mulx $aj, $m0, $alo ! ap[j]*bp[i]
- addxc $nj, %g0, $hi1 ! nhi=nj
- ldx [$np+0], $nj ! np[j]
- add $np, 8, $np
- umulxhi $aj, $m0, $aj ! ahi=aj
- addcc $lo0, $tj, $lo0 ! ap[j]*bp[i]+tp[j]
- mulx $nj, $m1, $nlo ! np[j]*m1
- addxc %g0, $hi0, $hi0
- umulxhi $nj, $m1, $nj ! nhi=nj
- addcc $lo1, $lo0, $lo1 ! np[j]*m1+ap[j]*bp[i]+tp[j]
- addxc %g0, $hi1, $hi1
- stx $lo1, [$tp] ! tp[j-1]
- add $tp, 8, $tp
- brnz,pt $cnt, .Linner
- sub $cnt, 8, $cnt
- !.Linner
- ldx [$tp+8], $tj ! tp[j]
- addcc $alo, $hi0, $lo0
- addxc $aj, %g0, $hi0 ! ahi=aj
- addcc $lo0, $tj, $lo0 ! ap[j]*bp[i]+tp[j]
- addxc %g0, $hi0, $hi0
- addcc $nlo, $hi1, $lo1
- addxc $nj, %g0, $hi1 ! nhi=nj
- addcc $lo1, $lo0, $lo1 ! np[j]*m1+ap[j]*bp[i]+tp[j]
- addxc %g0, $hi1, $hi1
- stx $lo1, [$tp] ! tp[j-1]
- subcc %g0, $ovf, %g0 ! move upmost overflow to CCR.xcc
- addxccc $hi1, $hi0, $hi1
- addxc %g0, %g0, $ovf
- stx $hi1, [$tp+8]
- add $tp, 16, $tp
- brnz,pt $i, .Louter
- sub $i, 8, $i
- sub $ap, $num, $ap ! rewind
- sub $np, $num, $np
- sub $tp, $num, $tp
- ba .Lsub
- subcc $num, 8, $cnt ! cnt=num-1 and clear CCR.xcc
- .align 16
- .Lsub:
- ldx [$tp], $tj
- add $tp, 8, $tp
- ldx [$np+0], $nj
- add $np, 8, $np
- subccc $tj, $nj, $t2 ! tp[j]-np[j]
- srlx $tj, 32, $tj
- srlx $nj, 32, $nj
- subccc $tj, $nj, $t3
- add $rp, 8, $rp
- st $t2, [$rp-4] ! reverse order
- st $t3, [$rp-8]
- brnz,pt $cnt, .Lsub
- sub $cnt, 8, $cnt
- sub $np, $num, $np ! rewind
- sub $tp, $num, $tp
- sub $rp, $num, $rp
- subc $ovf, %g0, $ovf ! handle upmost overflow bit
- and $tp, $ovf, $ap
- andn $rp, $ovf, $np
- or $np, $ap, $ap ! ap=borrow?tp:rp
- ba .Lcopy
- sub $num, 8, $cnt
- .align 16
- .Lcopy: ! copy or in-place refresh
- ldx [$ap+0], $t2
- add $ap, 8, $ap
- stx %g0, [$tp] ! zap
- add $tp, 8, $tp
- stx $t2, [$rp+0]
- add $rp, 8, $rp
- brnz $cnt, .Lcopy
- sub $cnt, 8, $cnt
- mov 1, %o0
- ret
- restore
- .type bn_mul_mont_t4, #function
- .size bn_mul_mont_t4, .-bn_mul_mont_t4
- ___
- # int bn_mul_mont_gather5(
- $rp="%o0"; # u64 *rp,
- $ap="%o1"; # const u64 *ap,
- $bp="%o2"; # const u64 *pwrtbl,
- $np="%o3"; # const u64 *np,
- $n0p="%o4"; # const BN_ULONG *n0,
- $num="%o5"; # int num, # caller ensures that num is >=3
- # int power);
- $code.=<<___;
- .globl bn_mul_mont_gather5_t4
- .align 32
- bn_mul_mont_gather5_t4:
- add %sp, STACK_BIAS, %g4 ! real top of stack
- sll $num, 3, $num ! size in bytes
- add $num, 63, %g1
- andn %g1, 63, %g1 ! buffer size rounded up to 64 bytes
- sub %g4, %g1, %g1
- andn %g1, 63, %g1 ! align at 64 byte
- sub %g1, STACK_FRAME, %g1 ! new top of stack
- sub %g1, %g4, %g1
- LDPTR [%sp+STACK_7thARG], %g4 ! load power, 7th argument
- save %sp, %g1, %sp
- ___
- # +-------------------------------+<----- %sp
- # . .
- # +-------------------------------+<----- aligned at 64 bytes
- # | __int64 tmp[0] |
- # +-------------------------------+
- # . .
- # . .
- # +-------------------------------+<----- aligned at 64 bytes
- # . .
- ($rp,$ap,$bp,$np,$n0p,$num)=map("%i$_",(0..5));
- ($t0,$t1,$t2,$t3,$cnt,$tp,$bufsz,$ccr)=map("%l$_",(0..7));
- ($ovf,$i)=($t0,$t1);
- &load_ccr($bp,"%g4",$ccr);
- &load_b($bp,$m0,"%o7"); # m0=bp[0]
- $code.=<<___;
- ld [$n0p+0], $t0 ! pull n0[0..1] value
- ld [$n0p+4], $t1
- add %sp, STACK_BIAS+STACK_FRAME, $tp
- sllx $t1, 32, $n0
- or $t0, $n0, $n0
- ldx [$ap+0], $aj ! ap[0]
- mulx $aj, $m0, $lo0 ! ap[0]*bp[0]
- umulxhi $aj, $m0, $hi0
- ldx [$ap+8], $aj ! ap[1]
- add $ap, 16, $ap
- ldx [$np+0], $nj ! np[0]
- mulx $lo0, $n0, $m1 ! "tp[0]"*n0
- mulx $aj, $m0, $alo ! ap[1]*bp[0]
- umulxhi $aj, $m0, $aj ! ahi=aj
- mulx $nj, $m1, $lo1 ! np[0]*m1
- umulxhi $nj, $m1, $hi1
- ldx [$np+8], $nj ! np[1]
- addcc $lo0, $lo1, $lo1
- add $np, 16, $np
- addxc %g0, $hi1, $hi1
- mulx $nj, $m1, $nlo ! np[1]*m1
- umulxhi $nj, $m1, $nj ! nhi=nj
- ba .L1st_g5
- sub $num, 24, $cnt ! cnt=num-3
- .align 16
- .L1st_g5:
- addcc $alo, $hi0, $lo0
- addxc $aj, %g0, $hi0
- ldx [$ap+0], $aj ! ap[j]
- addcc $nlo, $hi1, $lo1
- add $ap, 8, $ap
- addxc $nj, %g0, $hi1 ! nhi=nj
- ldx [$np+0], $nj ! np[j]
- mulx $aj, $m0, $alo ! ap[j]*bp[0]
- add $np, 8, $np
- umulxhi $aj, $m0, $aj ! ahi=aj
- mulx $nj, $m1, $nlo ! np[j]*m1
- addcc $lo0, $lo1, $lo1 ! np[j]*m1+ap[j]*bp[0]
- umulxhi $nj, $m1, $nj ! nhi=nj
- addxc %g0, $hi1, $hi1
- stxa $lo1, [$tp]0xe2 ! tp[j-1]
- add $tp, 8, $tp ! tp++
- brnz,pt $cnt, .L1st_g5
- sub $cnt, 8, $cnt ! j--
- !.L1st_g5
- addcc $alo, $hi0, $lo0
- addxc $aj, %g0, $hi0 ! ahi=aj
- addcc $nlo, $hi1, $lo1
- addxc $nj, %g0, $hi1
- addcc $lo0, $lo1, $lo1 ! np[j]*m1+ap[j]*bp[0]
- addxc %g0, $hi1, $hi1
- stxa $lo1, [$tp]0xe2 ! tp[j-1]
- add $tp, 8, $tp
- addcc $hi0, $hi1, $hi1
- addxc %g0, %g0, $ovf ! upmost overflow bit
- stxa $hi1, [$tp]0xe2
- add $tp, 8, $tp
- ba .Louter_g5
- sub $num, 16, $i ! i=num-2
- .align 16
- .Louter_g5:
- wr $ccr, %g0, %ccr
- ___
- &load_b($bp,$m0); # m0=bp[i]
- $code.=<<___;
- sub $ap, $num, $ap ! rewind
- sub $np, $num, $np
- sub $tp, $num, $tp
- ldx [$ap+0], $aj ! ap[0]
- ldx [$np+0], $nj ! np[0]
- mulx $aj, $m0, $lo0 ! ap[0]*bp[i]
- ldx [$tp], $tj ! tp[0]
- umulxhi $aj, $m0, $hi0
- ldx [$ap+8], $aj ! ap[1]
- addcc $lo0, $tj, $lo0 ! ap[0]*bp[i]+tp[0]
- mulx $aj, $m0, $alo ! ap[1]*bp[i]
- addxc %g0, $hi0, $hi0
- mulx $lo0, $n0, $m1 ! tp[0]*n0
- umulxhi $aj, $m0, $aj ! ahi=aj
- mulx $nj, $m1, $lo1 ! np[0]*m1
- add $ap, 16, $ap
- umulxhi $nj, $m1, $hi1
- ldx [$np+8], $nj ! np[1]
- add $np, 16, $np
- addcc $lo1, $lo0, $lo1
- mulx $nj, $m1, $nlo ! np[1]*m1
- addxc %g0, $hi1, $hi1
- umulxhi $nj, $m1, $nj ! nhi=nj
- ba .Linner_g5
- sub $num, 24, $cnt ! cnt=num-3
- .align 16
- .Linner_g5:
- addcc $alo, $hi0, $lo0
- ldx [$tp+8], $tj ! tp[j]
- addxc $aj, %g0, $hi0 ! ahi=aj
- ldx [$ap+0], $aj ! ap[j]
- add $ap, 8, $ap
- addcc $nlo, $hi1, $lo1
- mulx $aj, $m0, $alo ! ap[j]*bp[i]
- addxc $nj, %g0, $hi1 ! nhi=nj
- ldx [$np+0], $nj ! np[j]
- add $np, 8, $np
- umulxhi $aj, $m0, $aj ! ahi=aj
- addcc $lo0, $tj, $lo0 ! ap[j]*bp[i]+tp[j]
- mulx $nj, $m1, $nlo ! np[j]*m1
- addxc %g0, $hi0, $hi0
- umulxhi $nj, $m1, $nj ! nhi=nj
- addcc $lo1, $lo0, $lo1 ! np[j]*m1+ap[j]*bp[i]+tp[j]
- addxc %g0, $hi1, $hi1
- stx $lo1, [$tp] ! tp[j-1]
- add $tp, 8, $tp
- brnz,pt $cnt, .Linner_g5
- sub $cnt, 8, $cnt
- !.Linner_g5
- ldx [$tp+8], $tj ! tp[j]
- addcc $alo, $hi0, $lo0
- addxc $aj, %g0, $hi0 ! ahi=aj
- addcc $lo0, $tj, $lo0 ! ap[j]*bp[i]+tp[j]
- addxc %g0, $hi0, $hi0
- addcc $nlo, $hi1, $lo1
- addxc $nj, %g0, $hi1 ! nhi=nj
- addcc $lo1, $lo0, $lo1 ! np[j]*m1+ap[j]*bp[i]+tp[j]
- addxc %g0, $hi1, $hi1
- stx $lo1, [$tp] ! tp[j-1]
- subcc %g0, $ovf, %g0 ! move upmost overflow to CCR.xcc
- addxccc $hi1, $hi0, $hi1
- addxc %g0, %g0, $ovf
- stx $hi1, [$tp+8]
- add $tp, 16, $tp
- brnz,pt $i, .Louter_g5
- sub $i, 8, $i
- sub $ap, $num, $ap ! rewind
- sub $np, $num, $np
- sub $tp, $num, $tp
- ba .Lsub_g5
- subcc $num, 8, $cnt ! cnt=num-1 and clear CCR.xcc
- .align 16
- .Lsub_g5:
- ldx [$tp], $tj
- add $tp, 8, $tp
- ldx [$np+0], $nj
- add $np, 8, $np
- subccc $tj, $nj, $t2 ! tp[j]-np[j]
- srlx $tj, 32, $tj
- srlx $nj, 32, $nj
- subccc $tj, $nj, $t3
- add $rp, 8, $rp
- st $t2, [$rp-4] ! reverse order
- st $t3, [$rp-8]
- brnz,pt $cnt, .Lsub_g5
- sub $cnt, 8, $cnt
- sub $np, $num, $np ! rewind
- sub $tp, $num, $tp
- sub $rp, $num, $rp
- subc $ovf, %g0, $ovf ! handle upmost overflow bit
- and $tp, $ovf, $ap
- andn $rp, $ovf, $np
- or $np, $ap, $ap ! ap=borrow?tp:rp
- ba .Lcopy_g5
- sub $num, 8, $cnt
- .align 16
- .Lcopy_g5: ! copy or in-place refresh
- ldx [$ap+0], $t2
- add $ap, 8, $ap
- stx %g0, [$tp] ! zap
- add $tp, 8, $tp
- stx $t2, [$rp+0]
- add $rp, 8, $rp
- brnz $cnt, .Lcopy_g5
- sub $cnt, 8, $cnt
- mov 1, %o0
- ret
- restore
- .type bn_mul_mont_gather5_t4, #function
- .size bn_mul_mont_gather5_t4, .-bn_mul_mont_gather5_t4
- ___
- }
- $code.=<<___;
- .globl bn_flip_t4
- .align 32
- bn_flip_t4:
- .Loop_flip:
- ld [%o1+0], %o4
- sub %o2, 1, %o2
- ld [%o1+4], %o5
- add %o1, 8, %o1
- st %o5, [%o0+0]
- st %o4, [%o0+4]
- brnz %o2, .Loop_flip
- add %o0, 8, %o0
- retl
- nop
- .type bn_flip_t4, #function
- .size bn_flip_t4, .-bn_flip_t4
- .globl bn_flip_n_scatter5_t4
- .align 32
- bn_flip_n_scatter5_t4:
- sll %o3, 3, %o3
- srl %o1, 1, %o1
- add %o3, %o2, %o2 ! &pwrtbl[pwr]
- sub %o1, 1, %o1
- .Loop_flip_n_scatter5:
- ld [%o0+0], %o4 ! inp[i]
- ld [%o0+4], %o5
- add %o0, 8, %o0
- sllx %o5, 32, %o5
- or %o4, %o5, %o5
- stx %o5, [%o2]
- add %o2, 32*8, %o2
- brnz %o1, .Loop_flip_n_scatter5
- sub %o1, 1, %o1
- retl
- nop
- .type bn_flip_n_scatter5_t4, #function
- .size bn_flip_n_scatter5_t4, .-bn_flip_n_scatter5_t4
- .globl bn_gather5_t4
- .align 32
- bn_gather5_t4:
- ___
- &load_ccr("%o2","%o3","%g1");
- $code.=<<___;
- sub %o1, 1, %o1
- .Loop_gather5:
- ___
- &load_b("%o2","%g1");
- $code.=<<___;
- stx %g1, [%o0]
- add %o0, 8, %o0
- brnz %o1, .Loop_gather5
- sub %o1, 1, %o1
- retl
- nop
- .type bn_gather5_t4, #function
- .size bn_gather5_t4, .-bn_gather5_t4
- .asciz "Montgomery Multiplication for SPARC T4, David S. Miller, Andy Polyakov"
- .align 4
- ___
- &emit_assembler();
- close STDOUT;
|