diff --git a/crypto/CMakeLists.txt b/crypto/CMakeLists.txt index 664b6ac61..f49eb3b09 100644 --- a/crypto/CMakeLists.txt +++ b/crypto/CMakeLists.txt @@ -41,6 +41,7 @@ function(perlasm dest src) COMMAND ${PERL_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/${src} ${PERLASM_STYLE} ${PERLASM_FLAGS} ${ARGN} > ${dest} DEPENDS ${src} + ${PROJECT_SOURCE_DIR}/crypto/perlasm/arm-xlate.pl ${PROJECT_SOURCE_DIR}/crypto/perlasm/x86_64-xlate.pl ${PROJECT_SOURCE_DIR}/crypto/perlasm/x86asm.pl ${PROJECT_SOURCE_DIR}/crypto/perlasm/x86gas.pl diff --git a/crypto/aes/asm/aesv8-armx.pl b/crypto/aes/asm/aesv8-armx.pl index 1e93f8685..06754090b 100644 --- a/crypto/aes/asm/aesv8-armx.pl +++ b/crypto/aes/asm/aesv8-armx.pl @@ -28,7 +28,15 @@ # Cortex-A57 3.64 1.34 1.32 $flavour = shift; -open STDOUT,">".shift; +$output = shift; + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or +( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or +die "can't locate arm-xlate.pl"; + +open OUT,"| \"$^X\" $xlate $flavour $output"; +*STDOUT=*OUT; $prefix="aes_v8"; @@ -56,7 +64,7 @@ my ($zero,$rcon,$mask,$in0,$in1,$tmp,$key)= $code.=<<___; .align 5 -rcon: +.Lrcon: .long 0x01,0x01,0x01,0x01 .long 0x0c0f0e0d,0x0c0f0e0d,0x0c0f0e0d,0x0c0f0e0d // rotate-n-splat .long 0x1b,0x1b,0x1b,0x1b @@ -85,7 +93,7 @@ $code.=<<___; tst $bits,#0x3f b.ne .Lenc_key_abort - adr $ptr,rcon + adr $ptr,.Lrcon cmp $bits,#192 veor $zero,$zero,$zero diff --git a/crypto/modes/asm/ghashv8-armx.pl b/crypto/modes/asm/ghashv8-armx.pl index 54a1ac4db..7bbe2fc00 100644 --- a/crypto/modes/asm/ghashv8-armx.pl +++ b/crypto/modes/asm/ghashv8-armx.pl @@ -26,7 +26,15 @@ # (*) presented for reference/comparison purposes; $flavour = shift; -open STDOUT,">".shift; +$output = shift; + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or +( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or +die "can't locate arm-xlate.pl"; + +open OUT,"| \"$^X\" $xlate $flavour $output"; +*STDOUT=*OUT; $Xi="x0"; # argument block $Htbl="x1"; diff --git a/crypto/perlasm/arm-xlate.pl b/crypto/perlasm/arm-xlate.pl new file mode 100755 index 000000000..fd185e9c1 --- /dev/null +++ b/crypto/perlasm/arm-xlate.pl @@ -0,0 +1,140 @@ +#!/usr/bin/env perl + +# ARM assembler distiller by . + +my $flavour = shift; +my $output = shift; +open STDOUT,">$output" || die "can't open $output: $!"; + +$flavour = "linux32" if (!$flavour or $flavour eq "void"); + +my %GLOBALS; +my $dotinlocallabels=($flavour=~/linux/)?1:0; + +################################################################ +# directives which need special treatment on different platforms +################################################################ +my $arch = sub { + if ($flavour =~ /linux/) { ".arch\t".join(',',@_); } + else { ""; } +}; +my $globl = sub { + my $name = shift; + my $global = \$GLOBALS{$name}; + my $ret; + + SWITCH: for ($flavour) { + /ios/ && do { $name = "_$name"; + last; + }; + } + + $ret = ".globl $name" if (!$ret); + $$global = $name; + $ret; +}; +my $global = $globl; +my $extern = sub { + &$globl(@_); + return; # return nothing +}; +my $type = sub { + if ($flavour =~ /linux/) { ".type\t".join(',',@_); } + else { ""; } +}; +my $size = sub { + if ($flavour =~ /linux/) { ".size\t".join(',',@_); } + else { ""; } +}; +my $inst = sub { + if ($flavour =~ /linux/) { ".inst\t".join(',',@_); } + else { ".long\t".join(',',@_); } +}; +my $asciz = sub { + my $line = join(",",@_); + if ($line =~ /^"(.*)"$/) + { ".byte " . join(",",unpack("C*",$1),0) . "\n.align 2"; } + else + { ""; } +}; + +sub range { + my ($r,$sfx,$start,$end) = @_; + + join(",",map("$r$_$sfx",($start..$end))); +} + +sub parse_args { + my $line = shift; + my @ret = (); + + pos($line)=0; + + while (1) { + if ($line =~ m/\G\[/gc) { + $line =~ m/\G([^\]]+\][^,]*)\s*/g; + push @ret,"[$1"; + } + elsif ($line =~ m/\G\{/gc) { + $line =~ m/\G([^\}]+\}[^,]*)\s*/g; + my $arg = $1; + $arg =~ s/([rdqv])([0-9]+)([^\-]*)\-\1([0-9]+)\3/range($1,$3,$2,$4)/ge; + push @ret,"{$arg"; + } + elsif ($line =~ m/\G([^,]+)\s*/g) { + push @ret,$1; + } + + last if ($line =~ m/\G$/gc); + + $line =~ m/\G,\s*/g; + } + + map {my $s=$_;$s=~s/\b(\w+)/$GLOBALS{$1} or $1/ge;$s} @ret; +} + +while($line=<>) { + + $line =~ s|/\*.*\*/||; # get rid of C-style comments... + $line =~ s|^\s+||; # ... and skip white spaces in beginning... + $line =~ s|\s+$||; # ... and at the end + + { + $line =~ s|[\b\.]L(\w+)|L$1|g; # common denominator for Locallabel + $line =~ s|\bL(\w+)|\.L$1|g if ($dotinlocallabels); + } + + { + $line =~ s|(^[\.\w]+)\:\s*||; + my $label = $1; + if ($label) { + printf "%s:",($GLOBALS{$label} or $label); + } + } + + if ($line !~ m/^#/o) { + $line =~ s|^\s*(\.?)(\S+)\s*||o; + my $c = $1; $c = "\t" if ($c eq ""); + my $mnemonic = $2; + my $opcode; + if ($mnemonic =~ m/([^\.]+)\.([^\.]+)/o) { + $opcode = eval("\$$1_$2"); + } else { + $opcode = eval("\$$mnemonic"); + } + + my @args=parse_args($line); + + if (ref($opcode) eq 'CODE') { + $line = &$opcode(@args); + } elsif ($mnemonic) { + $line = $c.$mnemonic; + $line.= "\t".join(',',@args) if ($#args>=0); + } + } + + print $line if ($line); + print "\n"; +} + +close STDOUT; diff --git a/crypto/sha/asm/sha1-armv8.pl b/crypto/sha/asm/sha1-armv8.pl index deb1238d3..6be862434 100644 --- a/crypto/sha/asm/sha1-armv8.pl +++ b/crypto/sha/asm/sha1-armv8.pl @@ -20,7 +20,15 @@ # (*) Software results are presented mostly for reference purposes. $flavour = shift; -open STDOUT,">".shift; +$output = shift; + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or +( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or +die "can't locate arm-xlate.pl"; + +open OUT,"| \"$^X\" $xlate $flavour $output"; +*STDOUT=*OUT; ($ctx,$inp,$num)=("x0","x1","x2"); @Xw=map("w$_",(3..17,19)); @@ -154,6 +162,7 @@ $code.=<<___; .text +.extern OPENSSL_armcap_P .globl sha1_block_data_order .type sha1_block_data_order,%function .align 6 diff --git a/crypto/sha/asm/sha512-armv8.pl b/crypto/sha/asm/sha512-armv8.pl index 5a9c81291..e9f39f371 100644 --- a/crypto/sha/asm/sha512-armv8.pl +++ b/crypto/sha/asm/sha512-armv8.pl @@ -28,9 +28,21 @@ # and lags behind assembly only by 50-90%. $flavour=shift; +# Unlike most perlasm files, sha512-armv8.pl takes an additional argument to +# determine which hash function to emit. This differs from upstream OpenSSL so +# that the script may continue to output to stdout. +$variant=shift; $output=shift; -if ($output =~ /512/) { +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or +( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or +die "can't locate arm-xlate.pl"; + +open OUT,"| \"$^X\" $xlate $flavour $output"; +*STDOUT=*OUT; + +if ($variant eq "sha512") { $BITS=512; $SZ=8; @Sigma0=(28,34,39); @@ -39,7 +51,7 @@ if ($output =~ /512/) { @sigma1=(19,61, 6); $rounds=80; $reg_t="x"; -} else { +} elsif ($variant eq "sha256") { $BITS=256; $SZ=4; @Sigma0=( 2,13,22); @@ -48,6 +60,8 @@ if ($output =~ /512/) { @sigma1=(17,19,10); $rounds=64; $reg_t="w"; +} else { + die "Unknown variant: $variant"; } $func="sha${BITS}_block_data_order"; @@ -152,6 +166,7 @@ $code.=<<___; .text +.extern OPENSSL_armcap_P .globl $func .type $func,%function .align 6 @@ -181,7 +196,7 @@ $code.=<<___; ldp $E,$F,[$ctx,#4*$SZ] add $num,$inp,$num,lsl#`log(16*$SZ)/log(2)` // end of input ldp $G,$H,[$ctx,#6*$SZ] - adr $Ktbl,K$BITS + adr $Ktbl,.LK$BITS stp $ctx,$num,[x29,#96] .Loop: @@ -231,8 +246,8 @@ $code.=<<___; .size $func,.-$func .align 6 -.type K$BITS,%object -K$BITS: +.type .LK$BITS,%object +.LK$BITS: ___ $code.=<<___ if ($SZ==8); .quad 0x428a2f98d728ae22,0x7137449123ef65cd @@ -297,7 +312,7 @@ $code.=<<___ if ($SZ==4); .long 0 //terminator ___ $code.=<<___; -.size K$BITS,.-K$BITS +.size .LK$BITS,.-.LK$BITS .align 3 .LOPENSSL_armcap_P: .quad OPENSSL_armcap_P-. @@ -322,7 +337,7 @@ sha256_block_armv8: add x29,sp,#0 ld1.32 {$ABCD,$EFGH},[$ctx] - adr $Ktbl,K256 + adr $Ktbl,.LK256 .Loop_hw: ld1 {@MSG[0]-@MSG[3]},[$inp],#64