diff options
author | Andy Polyakov <appro@openssl.org> | 2011-06-04 12:20:45 +0000 |
---|---|---|
committer | Andy Polyakov <appro@openssl.org> | 2011-06-04 12:20:45 +0000 |
commit | 301799b803fc9f3e2adaad32b1ccace736bbe7cc (patch) | |
tree | 0edc73d8425ac47b5124104760cb0294c53b214f /crypto | |
parent | 8d515259e2a4631a5b42f1a072b0ff6f8eba189c (diff) |
x86[_64]cpuid.pl: add function accessing rdrand instruction.
Diffstat (limited to 'crypto')
-rwxr-xr-x | crypto/perlasm/x86_64-xlate.pl | 15 | ||||
-rw-r--r-- | crypto/perlasm/x86asm.pl | 8 | ||||
-rw-r--r-- | crypto/x86_64cpuid.pl | 23 | ||||
-rw-r--r-- | crypto/x86cpuid.pl | 12 |
4 files changed, 56 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(); |