Commit 301799b8 authored by Andy Polyakov's avatar Andy Polyakov
Browse files

x86[_64]cpuid.pl: add function accessing rdrand instruction.

parent 8d515259
Loading
Loading
Loading
Loading
+14 −1
Original line number Diff line number Diff line
@@ -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
+8 −0
Original line number Diff line number Diff line
@@ -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";
+22 −1
Original line number Diff line number Diff line
@@ -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
+12 −0
Original line number Diff line number Diff line
@@ -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();
+2 −0
Original line number Diff line number Diff line
@@ -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