summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xcrypto/perlasm/x86_64-xlate.pl15
-rw-r--r--crypto/perlasm/x86asm.pl8
-rw-r--r--crypto/x86_64cpuid.pl23
-rw-r--r--crypto/x86cpuid.pl12
-rw-r--r--doc/crypto/OPENSSL_ia32cap.pod2
5 files changed, 58 insertions, 2 deletions
diff --git a/crypto/perlasm/x86_64-xlate.pl b/crypto/perlasm/x86_64-xlate.pl
index 91017c69f3..a6b718b5e8 100755
--- a/crypto/perlasm/x86_64-xlate.pl
+++ b/crypto/perlasm/x86_64-xlate.pl
@@ -625,7 +625,7 @@ my %globals;
/\.comm/ && do { my @str=split(/,\s*/,$line);
my $v=undef;
if ($nasm) {
- $v.="common $prefix@str[0] @str[1]:near";
+ $v.="common $prefix@str[0] @str[1]";
} else {
$v="$current_segment\tENDS\n" if ($current_segment);
$current_segment = ".data";
@@ -757,6 +757,19 @@ my $pclmulqdq = sub {
}
};
+my $rdrand = sub {
+ if (shift =~ /%[er](\w+)/) {
+ my @opcode=();
+ my $dst=$1;
+ if ($dst !~ /[0-9]+/) { $dst = $regrm{"%e$dst"}; }
+ rex(\@opcode,0,$1,8);
+ push @opcode,0x0f,0xc7,0xf0|($dst&7);
+ @opcode;
+ } else {
+ ();
+ }
+};
+
if ($nasm) {
print <<___;
default rel
diff --git a/crypto/perlasm/x86asm.pl b/crypto/perlasm/x86asm.pl
index efa7b61ce8..b7ddb8137f 100644
--- a/crypto/perlasm/x86asm.pl
+++ b/crypto/perlasm/x86asm.pl
@@ -123,6 +123,14 @@ sub ::pclmulqdq
{ &::generic("pclmulqdq",@_); }
}
+sub ::rdrand
+{ my ($dst)=@_;
+ if ($dst =~ /(e[a-dsd][ixp])/)
+ { &::data_byte(0x0f,0xc7,0xf0|$regrm{$dst}); }
+ else
+ { &::generic("rdrand",@_); }
+}
+
# label management
$lbdecor="L"; # local label decoration, set by package
$label="000";
diff --git a/crypto/x86_64cpuid.pl b/crypto/x86_64cpuid.pl
index 7b76522bd8..26b8e5cc08 100644
--- a/crypto/x86_64cpuid.pl
+++ b/crypto/x86_64cpuid.pl
@@ -7,7 +7,11 @@ if ($flavour =~ /\./) { $output = $flavour; undef $flavour; }
$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/);
$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
-open STDOUT,"| $^X ${dir}perlasm/x86_64-xlate.pl $flavour $output";
+( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or
+( $xlate="${dir}perlasm/x86_64-xlate.pl" and -f $xlate) or
+die "can't locate x86_64-xlate.pl";
+
+open STDOUT,"| $^X $xlate $flavour $output";
($arg1,$arg2,$arg3,$arg4)=$win64?("%rcx","%rdx","%r8", "%r9") : # Win64 order
("%rdi","%rsi","%rdx","%rcx"); # Unix order
@@ -349,4 +353,21 @@ OPENSSL_instrument_bus2:
___
}
+print<<___;
+.globl OPENSSL_ia32_rdrand
+.type OPENSSL_ia32_rdrand,\@abi-omnipotent
+.align 16
+OPENSSL_ia32_rdrand:
+ mov \$8,%ecx
+.Loop_rdrand:
+ rdrand %rax
+ jc .Lbreak_rdrand
+ loop .Loop_rdrand
+.Lbreak_rdrand:
+ cmp \$0,%rax
+ cmove %rcx,%rax
+ ret
+.size OPENSSL_ia32_rdrand,.-OPENSSL_ia32_rdarnd
+___
+
close STDOUT; # flush
diff --git a/crypto/x86cpuid.pl b/crypto/x86cpuid.pl
index 70c8a2d671..6595ff35fc 100644
--- a/crypto/x86cpuid.pl
+++ b/crypto/x86cpuid.pl
@@ -442,6 +442,18 @@ my $max = "ebp";
&function_end("OPENSSL_instrument_bus2");
}
+&function_begin_B("OPENSSL_ia32_rdrand");
+ &mov ("ecx",8);
+&set_label("loop");
+ &rdrand ("eax");
+ &jc (&label("break"));
+ &loop (&label("loop"));
+&set_label("break");
+ &cmp ("eax",0);
+ &cmove ("eax","ecx");
+ &ret ();
+&function_end_B("OPENSSL_ia32_rdrand");
+
&initseg("OPENSSL_cpuid_setup");
&asm_finish();
diff --git a/doc/crypto/OPENSSL_ia32cap.pod b/doc/crypto/OPENSSL_ia32cap.pod
index 3f6458c6bd..17189ed843 100644
--- a/doc/crypto/OPENSSL_ia32cap.pod
+++ b/doc/crypto/OPENSSL_ia32cap.pod
@@ -51,6 +51,8 @@ moment of this writing following bits are significant:
=item bit #60 denoting AVX extension;
+=item bit #62 denoting availability of RDRAND instruction;
+
For example, clearing bit #26 at run-time disables high-performance
SSE2 code present in the crypto library, while clearing bit #24
disables SSE2 code operating on 128-bit XMM register bank. You might